Subview UIImageView не займет горизонтальный центр в контейнере Superview UIView - PullRequest
0 голосов
/ 14 мая 2019

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

...