我创建了一个自定义iOS弹出视图以显示图像视图。如果imageview的高度大于宽度,则不会在弹出窗口中居中。弹出窗口是背景透明的屏幕盖,白色弹出框以及容器中的标题标签+ UIImageView +按钮。由于某些原因,UIImageView不会在弹出容器视图中居中。我以编程方式100%完成此操作,如下所示。
我尝试将imageView.center
设置为容器中心的点坐标,并设置superview.center
和containerView.center
。我已经尝试过CenterXAnchor
,Leading
和Trailing
锚点以及其他一些东西。我应该能够将其居中放置在代码中,但不会在运行时居中!发生了什么事将其搁置一旁,但我无法弄清楚,我的高级同辈也无法解决。
class AlertView: UIView, AlertViewModel {
// MARK: - UI Element Definitions
// Containers
internal lazy var backgroundView: UIView =
AlertViewUIElement.backgroundView()
internal lazy var containerView: UIView =
AlertViewUIElement.containerView()
// Content
private lazy var titleLabel: UILabel =
AlertViewUIElement.titleLabel()
private lazy var messageLabel: UILabel =
AlertViewUIElement.messageLabel()
private lazy var imageView: UIImageView =
AlertViewUIElement.imageView()
// Separator Elements
private lazy var separatorButtonTopLabel: UILabel = AlertViewUIElement.separatorLabel()
private lazy var separatorButtonMiddleLabel: UILabel = AlertViewUIElement.separatorLabel()
private lazy var bottomButtonSeparator: UILabel = AlertViewUIElement.separatorLabel()
// Buttons
private lazy var leftButton: UIButton = AlertViewUIElement.blueButton()
// Middle Button will be used for Three Button Popups
private lazy var middleButton: UIButton = AlertViewUIElement.blueButton()
// Right Button will be used for Single Button Popups
private lazy var rightButton: UIButton = AlertViewUIElement.redButton()
// Image Alert
convenience init(title: String, message: String? = nil, image: UIImage? = nil, leftButtonText: String? = nil, middleButtonText: String? = nil, rightButtonText: String = "Close", leftButton: (() -> ())? = nil, middleButton: (() -> ())? = nil, rightButton: (() -> ())? = nil) {
self.init(frame: UIScreen.main.bounds)
setupButtonActions(left: leftButton, middle: middleButton, right: rightButton)
setupViewConstraints(title: title, message: message, image: image, leftButtonText: leftButtonText, middleButtonText: middleButtonText, rightButtonText: rightButtonText)
}
// MARK: - Alert View Constraints Setup
private func setupViewConstraints(title: String, message: String?, image: UIImage?, leftButtonText: String?, middleButtonText: String?, rightButtonText: String) {
DispatchQueue.main.async {
self.setupBackgroundView()
self.setupContainerView()
self.setupTitleLabel()
self.titleLabel.text = title
if let image = image {
self.setupImageView(image: image)
}
self.setupSeperatorButtonTopLabel(showImage: image != nil)
self.setupTwoButtons()
self.leftButton.setTitle(leftButtonText, for: .normal)
self.rightButton.setTitle(rightButtonText, for: .normal)
}
}
// MARK: - Constraints
private func setupBackgroundView() {
backgroundView.frame = frame
addSubview(backgroundView)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissView))
tapGesture.numberOfTapsRequired = 1
backgroundView.addGestureRecognizer(tapGesture)
}
private func setupContainerView() {
backgroundView.addSubview(containerView)
let tapGesture = UITapGestureRecognizer(target: self, action: nil)
tapGesture.numberOfTapsRequired = 1
containerView.addGestureRecognizer(tapGesture)
containerView.centerYAnchor.constraint(equalTo: backgroundView.centerYAnchor, constant: 0.0).isActive = true
containerView.centerXAnchor.constraint(equalTo: backgroundView.centerXAnchor, constant: 0.0).isActive = true
if UIDevice.isPad() {
containerView.widthAnchor.constraint(equalToConstant: 450).isActive = true
} else {
containerView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.8).isActive = true
}
}
private func setupTitleLabel() {
containerView.addSubview(titleLabel)
titleLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 8).isActive = true
titleLabel.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 0.0).isActive = true
titleLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -8).isActive = true
titleLabel.heightAnchor.constraint(equalToConstant: 48).isActive = true
}
private func setupMessageLabel() {
containerView.addSubview(messageLabel)
messageLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 8).isActive = true
messageLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: contentPadding).isActive = true
messageLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -8).isActive = true
}
private func setupImageView(image: UIImage) {
// TODO Center
containerView.addSubview(imageView)
self.imageView.image = self.resizeImage(image)
// imageView.bindFrameToSuperviewBounds()
imageView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: contentPadding).isActive = true
// imageView.center.x = containerView.center.x
// imageView.centerXAnchor.constraint(equalTo: superview.centerXAnchor).isActive = true
// let trail = imageView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -8)
// let lead = imageView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 8)
// trail.priority = UILayoutPriority(rawValue: 999)
// lead.priority = UILayoutPriority(rawValue: 999)
// trail.isActive = true
// lead.isActive = true
}
private func setupSeperatorButtonTopLabel(showImage: Bool) {
containerView.addSubview(separatorButtonTopLabel)
separatorButtonTopLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
if showImage {
separatorButtonTopLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: contentPadding).isActive = true
} else {
separatorButtonTopLabel.topAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: contentPadding).isActive = true
}
separatorButtonTopLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true
separatorButtonTopLabel.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
}
// MARK: - Two Buttons
private func setupTwoButtons() {
// Two horizontal buttons
setupLeftButton()
containerView.addSubview(separatorButtonMiddleLabel)
separatorButtonMiddleLabel.leadingAnchor.constraint(equalTo: leftButton.trailingAnchor, constant: 0).isActive = true
separatorButtonMiddleLabel.topAnchor.constraint(equalTo: separatorButtonTopLabel.bottomAnchor, constant: 0).isActive = true
separatorButtonMiddleLabel.widthAnchor.constraint(equalToConstant: 1.0).isActive = true
separatorButtonMiddleLabel.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0).isActive = true
setupRightButton()
}
private func setupLeftButton() {
containerView.addSubview(leftButton)
leftButton.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 0).isActive = true
leftButton.topAnchor.constraint(equalTo: separatorButtonTopLabel.bottomAnchor, constant: 0).isActive = true
leftButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
leftButton.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0).isActive = true
}
private func setupRightButton() {
containerView.addSubview(rightButton)
rightButton.leadingAnchor.constraint(equalTo: separatorButtonMiddleLabel.trailingAnchor, constant: 0).isActive = true
rightButton.topAnchor.constraint(equalTo: leftButton.topAnchor, constant: 0.0).isActive = true
rightButton.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: 0).isActive = true
rightButton.heightAnchor.constraint(equalTo: leftButton.heightAnchor, constant: 0.0).isActive = true
rightButton.widthAnchor.constraint(equalTo: leftButton.widthAnchor, constant: 0.0).isActive = true
}
}
extension AlertViewModel where Self: UIView {
// MARK: - Show and Hide the Alert View
func show(animated: Bool) {
DispatchQueue.main.async {
self.backgroundView.alpha = 0
if var topController = UIApplication.shared.delegate?.window??.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
let subviewsList = topController.view.subviews
for view in subviewsList where view is AlertView {
view.removeFromSuperview()
break
}
topController.view.addSubview(self)
}
if animated {
self.containerView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
UIView.animate(withDuration: 0.24,
animations: {
self.backgroundView.alpha = 1.0
self.containerView.transform = .identity
},
completion: { _ in
self.backgroundView.alpha = 1.0
})
}
}
}
func dismiss(animated: Bool) {
DispatchQueue.main.async {
if animated {
self.backgroundView.alpha = 1.0
self.containerView.transform = .identity
UIView.animate(withDuration: 0.16,
animations: {
self.backgroundView.alpha = 0.0
self.containerView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
},
completion: { _ in
self.backgroundView.alpha = 0.0
self.removeFromSuperview()
})
} else {
self.backgroundView.alpha = 0.0
self.removeFromSuperview()
}
}
}
func resizeImage(_ image: UIImage) -> UIImage? {
// let newWidth = UIScreen.screenWidth * 0.6
// let newHeight = UIScreen.screenHeight * 0.2
// let scaledSize = CGSize(width: newWidth, height: newHeight)
// return image.imageWithSize(scaledSize)
let maxSize = CGSize(width: 295, height: 300)
let imageSize = image.size
var ratio: CGFloat = 0
if imageSize.width > imageSize.height {
ratio = maxSize.width / imageSize.width
} else {
ratio = maxSize.height / imageSize.height
}
let scaledSize = CGSize(width: imageSize.width * ratio, height: imageSize.height * ratio)
var resizedImage = image.imageWithSize(scaledSize)
if imageSize.height > imageSize.width {
let left = (maxSize.width - (resizedImage?.size.width ?? 0)) / 2
resizedImage = resizedImage?.withAlignmentRectInsets(UIEdgeInsets(top: 0, left: -left, bottom: 0, right: 0))
}
return resizedImage
}
}
可以使用init调用此弹出窗口,传递图像,并且该图像应位于容器框/弹出窗口的中心。有什么事我看不到还是做错了吗?谢谢