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.