Я сделал пользовательское всплывающее окно iOS, чтобы показать изображения. Если изображение более высокое, чем широкое, оно не будет центрироваться во всплывающем окне. Всплывающее окно представляет собой фоновую прозрачную крышку экрана, белое всплывающее окно и метку заголовка + кнопки 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, переданного изображения, и изображение должно центрироваться в окне контейнера / всплывающем окне. Что-то происходит, чего я не вижу, или я делаю это неправильно? Спасибо