2017-01-13 3 views
0

Я пытаюсь создать UIView, у которого есть свойство UIImage, которое устанавливает 2 UIImageView. Эффект, который я пытаюсь создать вид профиля и работает в раскадровке:Подкласс UIView с UIImageView внутри не отвечает на автоматическую компоновку

Profile View

Однако в моем приложении является то, что он не реагирует на авто-макет. В тот момент она конкретизируется в меню вид переполняет меню View Controller:

enter image description here

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) 

    } 
} 

ответ

2

Вы смесительный автоматическая компоновка и фреймворки и ожидание того, что кадры будут автоматически обновляться при перемещении или изменении ваших представлений. Этого не происходит.

Попробуйте сдерживающие взгляды на место, как:

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 
} 
+0

Примечание: Вышеприведенный код НЕ проверяет, были ли уже добавлены подвидные объекты. Если 'updateLayout' вызывается несколько раз, вы МОЖЕТЕ иметь несколько« blurredProfileView »и другие представления, которые были добавлены в функцию. – Brandon

+0

Я пробовал свой код и в Раскадровке, а также на тестовом устройстве, я получаю это как результат: http://imgur.com/a/Qz9ne. Размытость, а также меньший профиль, похоже, исчезают. Пользовательский UIView полностью ограничен, и ваш код, похоже, добавляет ограничения для профилей, но он не отвечает на него. – Emptyless

+0

Я попытался добавить heightAnchor, так как у моего storyBoard есть якорь высоты (4 ребра и высота): blurredProfileView.heightAnchor.constraint (equalTo: self.heightAnchor), но это не имеет никакого эффекта :( – Emptyless

0

Как сказал here, вы не должны манипулировать кадры, если вы планируете использовать autolayout

+0

Но я не устанавливаю рамку явно. Я использую self.bounds (локальные координаты) для создания фрейма для subView UIView. Этот фрейм должен обновляться, когда ограничения автоопределения изменяют границы UIView. В основном это делает так, что SubView всегда имеет тот же размер/фрейм, что и UIView. У меня есть представление в Storyboard. – Emptyless

+0

Да, но принятый ответ сообщения, который я связывал, явно указывает, что вы должны использовать -init вместо -initWithFrame :. вы пытались избавиться от всех этих CGRect, чтобы убедиться, что это лучше? – AnderCover

+0

Я использовал ответ Брэндона выше, чтобы исправить его :-), спасибо, хотя! – Emptyless

0

Если вы хотите обновить кадры/слои ваших подвиды/слоев вы можете сделать это только после того, как autolayout завершила свои вычисления кадров, т.е. переопределить layoutSubViews и двигаться ваш код кадра их. В качестве альтернативы используйте автомат. Поскольку вы просто хотите заполнить свой контроль, вы можете использовать следующее расширение:

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)}) 
     } 
    } 
Смежные вопросы