简体   繁体   中英

Subclass UIView with UIImageView inside not responding to auto-layout

I am trying to create a UIView which has a UIImage property that sets 2 UIImageView . The effect I'm trying to create is a profile view and is working in storyboard:

个人资料视图

However in my app is that it does not respond to auto-layout. The moment it is instantiated in a menu the view overflows the Menu View Controller:

在此处输入图片说明

import UIKit

@IBDesignable
class ProfileImageView: UIView {

    @IBInspectable
    var profileImage : UIImage = UIImage()

    @IBInspectable
    var topImageScalePercentage : CGFloat = 50

    override init(frame: CGRect) {
        super.init(frame: frame)
        updateLayout()
    }

    convenience init() {
        self.init(frame: CGRect.zero)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        updateLayout()
    }

    func updateLayout() {

        // Create the large background Image View
        let blurredProfileView = UIImageView(frame: self.bounds)
        blurredProfileView.image = profileImage
        blurredProfileView.contentMode = UIViewContentMode.scaleAspectFill
        blurredProfileView.layer.masksToBounds = true

        // Blur the background Image View
        let blurEffect = UIBlurEffect(style: .light)
        let blurView = UIVisualEffectView(effect: blurEffect)
        blurView.frame = blurredProfileView.bounds
        blurredProfileView.addSubview(blurView)

        // Add the Blurred Profile View to view
        self.addSubview(blurredProfileView)

        // Create smaller Profile Picture
        var profileRect : CGRect!
        if blurredProfileView.bounds.width < blurredProfileView.bounds.height {
            let width = blurredProfileView.bounds.width * topImageScalePercentage / 100.0
            let height = width // 1:1
            profileRect = CGRect(x: 0.0, y: 0.0, width: width, height: height)
        } else {
            let height = blurredProfileView.bounds.height * topImageScalePercentage / 100.0
            let width = height // 1:1
            profileRect = CGRect(x: 0.0, y: 0.0, width: width, height: height)
        }
        let profileImageView = UIImageView(frame: profileRect)
        profileImageView.image = profileImage
        profileImageView.contentMode = .scaleAspectFill
        profileImageView.layer.masksToBounds = true
        profileImageView.layer.cornerRadius = profileImageView.bounds.width / 2
        profileImageView.center = blurredProfileView.center

        self.addSubview(profileImageView)

    }
}

You are mixing auto-layout and frame-based layouts and expecting the frames to automatically update when your views move or resize. That does not happen.

Try constraining the views into place like:

func updateLayout() {

    // Create the large background Image View
    let blurredProfileView = UIImageView(image: profileImage)
    blurredProfileView.contentMode = UIViewContentMode.scaleAspectFill
    blurredProfileView.layer.masksToBounds = true

    self.addSubview(blurredProfileView)
    blurredProfileView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
    blurredProfileView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
    blurredProfileView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    blurredProfileView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    blurredProfileView.translatesAutoresizingMaskIntoConstraints = false


    // Blur the background Image View
    let blurEffect = UIBlurEffect(style: .light)
    let blurView = UIVisualEffectView(effect: blurEffect)

    blurredProfileView.addSubview(blurView)
    blurView.leftAnchor.constraint(equalTo: blurredProfileView.leftAnchor).isActive = true
    blurView.rightAnchor.constraint(equalTo: blurredProfileView.rightAnchor).isActive = true
    blurView.topAnchor.constraint(equalTo: blurredProfileView.topAnchor).isActive = true
    blurView.bottomAnchor.constraint(equalTo: blurredProfileView.bottomAnchor).isActive = true
    blurView.translatesAutoresizingMaskIntoConstraints = false



    // Create smaller Profile Picture
    var profileRect : CGRect!
    if blurredProfileView.bounds.width < blurredProfileView.bounds.height {
        let width = blurredProfileView.bounds.width * topImageScalePercentage / 100.0
        let height = width // 1:1
        profileRect = CGRect(x: 0.0, y: 0.0, width: width, height: height)
    }
    else {
        let height = blurredProfileView.bounds.height * topImageScalePercentage / 100.0
        let width = height // 1:1
        profileRect = CGRect(x: 0.0, y: 0.0, width: width, height: height)
    }

    let profileImageView = UIImageView(image: profileImage)
    profileImageView.contentMode = .scaleAspectFill
    profileImageView.layer.masksToBounds = true
    profileImageView.layer.cornerRadius = profileRect.width / 2

    self.addSubview(profileImageView)
    profileImageView.centerXAnchor.constraint(equalTo: blurredProfileView.centerXAnchor).isActive = true
    profileImageView.centerYAnchor.constraint(equalTo: blurredProfileView.centerYAnchor).isActive = true
    profileImageView.widthAnchor.constraint(equalToConstant: profileRect.width).isActive = true
    profileImageView.heightAnchor.constraint(equalToConstant: profileRect.height).isActive = true
    profileImageView.translatesAutoresizingMaskIntoConstraints = false
}

至于说在这里 ,你不应该操作框架,如果你打算使用自动布局

If you want to update the frames/layers of your subviews/layers you can only do this after autolayout has completed its frame calculations ie override layoutSubViews and move your frame code their. Alternatively use auto layout. Since you just want to fill your superview you can use the following extension:

    extension UIView {
        func constrainToSuperView() {
            translatesAutoresizingMaskIntoConstraints = false
            let attributes: [NSLayoutAttribute] = [.centerX, .centerY, .width, .height]
            NSLayoutConstraint.activate(attributes.map{NSLayoutConstraint(item: self, attribute: $0, relatedBy: .equal, toItem: self.superview, attribute: $0, multiplier: 1, constant: 0)})
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM