How to keep a round imageView round using auto layout?

后端 未结 15 1374
悲&欢浪女
悲&欢浪女 2020-12-01 06:22

How do I turn a rectangular image view into a circular image view that can hold shape in auto layout without setting width and height restraints? Thereby allowing the imageV

相关标签:
15条回答
  • 2020-12-01 06:29

    Setting radius in viewWillLayoutSubviews will solve the problem

    override func viewWillLayoutSubviews() {
      super.viewWillLayoutSubviews()
      profileImageView.layer.cornerRadius = profileImageView.frame.height / 2.0
    }
    
    0 讨论(0)
  • 2020-12-01 06:32

    With my hacky solution you'll get smooth corner radius animation alongside frame size change.

    Let's say you have ViewSubclass : UIView. It should contain the following code:

    class ViewSubclass: UIView {
        var animationDuration : TimeInterval?
        let imageView = UIImageView()
        //some imageView setup code
    
        override func layoutSubviews() {
            super.layoutSubviews()
    
            if let duration = animationDuration {
                let anim = CABasicAnimation(keyPath: "cornerRadius")
                anim.fromValue = self.imageView.cornerRadius
                let radius = self.imageView.frame.size.width / 2
                anim.toValue = radius
                anim.duration = duration
                self.imageView.layer.cornerRadius = radius
                self.imageView.layer.add(anim, forKey: "cornerRadius")
            } else {
                imageView.cornerRadius = imageView.frame.size.width / 2
            }
    
            animationDuration = nil
        }
    }
    

    An then you'll have to do this:

    let duration = 0.4 //For example
    instanceOfViewSubclass.animationDuration = duration
    UIView.animate(withDuration: duration, animations: { 
        //Your animation
        instanceOfViewSubclass.layoutIfNeeded()
    })
    

    It's not beautiful, and might not work for complex multi-animations, but does answer the question.

    0 讨论(0)
  • 2020-12-01 06:36

    I have same problem, and Now I get what happened here, hope some ideas can help you: there are something different between the tows:

    1. your profileImageView in storyboard
    2. your profileImageView in viewDidLoad

    the size of bound and frame is different when viewDidLoad and in storyboard,just because view is resize for different device size. You can try it print(profileImageView.bounds.size) in viewDidLoad and viewDidAppear you will find the size in viewDidLoad you set cornerRadius is not the real "running" size.

    a tips for you: you can use a subClass of ImageView to avoid it, or do not use it in storyboard,

    0 讨论(0)
  • 2020-12-01 06:38

    Unfortunately you cannot do this using cornerRadius and autolayout — the CGLayer is not affected by autolayout, so any change in the size of the view will not change the radius which has been set once causing, as you have noticed, the circle to lose its shape.

    You can create a custom subclass of UIImageView and override layoutSubviews in order to set the cornerRadius each time the bounds of the imageview change.

    EDIT

    An example might look something like this:

    class Foo: UIImageView {
        override func layoutSubviews() {
            super.layoutSubviews()
    
            let radius: CGFloat = self.bounds.size.width / 2.0
    
            self.layer.cornerRadius = radius
        }
    }
    

    And obviously you would have to constrain the Foobar instance's width to be the same as the height (to maintain a circle). You would probably also want to set the Foobar instance's contentMode to UIViewContentMode.ScaleAspectFill so that it knows how to draw the image (this means that the image is likely to be cropped).

    0 讨论(0)
  • 2020-12-01 06:38

    It seems when you add one view as a subview of another that netted view will not necessarily have the same height as its superview. That's what the problem seems like. The solution is to not add your imageView as a subview, but have it on top of your backgroundView. In the image below I'm using a UILabel as my backgroundView.

    Also in your case, when you're setting the cornerRadius use this: let radius: CGFloat = self.bounds.size.height / 2.0.

    0 讨论(0)
  • 2020-12-01 06:39

    Can be easily done by creating an IBOutlet for the constraint which needs to be changed at runtime. Below is the code:

    1. Create a IBOutlet for the constraint that needs to be changed at run time.

      @IBOutlet var widthConstraint: NSLayoutConstraint!
      
    2. Add below code in viewDidLoad():

      self.widthConstraint.constant = imageWidthConstraintConstant()
      

    Below function determines for device types change the width constraint accordingly.

    func imageWidthConstraintConstant() -> CGFloat {
    
        switch(self.screenWidth()) {
    
        case 375:
            return 100
    
        case 414:
            return 120
    
        case 320:
            return 77
    
        default:
            return 77
        }
    }
    
    0 讨论(0)
提交回复
热议问题