2015-04-02 3 views
0

У меня есть три горизонтально выровненных UIView s в контейнере UIView. Эти три вида должны охватывать всю ширину выше UIImageView. Проблема, однако, заключается в том, что иногда следует показывать только один или два дочерних представления.Рассматривать константу NSLayoutConstraint как множитель?

Я создал свой вид иерархию как так:

enter image description here

Поскольку мнения ребенка устанавливается равной шириной первого ребенка (который всегда будет показан), я просто установить ширина первого дочернего элемента - это часть ширины UIImageView. Поэтому, если нужно показать три вида ребенка, первый вид ребенка будет иметь множитель 1/3 ширины UIImageView. Если нужно отобразить два представления для детей, множитель будет равен 1/2. Если только один, множитель будет равен 1.

Это казалось идеальным решением, однако свойство множителя читается только. Моя первая попытка решить это была путем создания трех разных NSLayoutConstraint s, прикрепленных к первому детскому виду, все с другим множителем, из которых 2/3 из них отключены. Затем, во время выполнения, я бы включил соответствующую константу с соответствующим множителем, основанным на количестве просмотров, которые я хотел показать.

Это привело много некрасивых ошибок, и поэтому сделал свое второе решение:

var constraint = NSLayoutConstraint(item: color1, attribute:NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: imageView, attribute: NSLayoutAttribute.Width, multiplier: 1/2, constant: 0) 
view.addConstraint(constraint) 

Где я хотел бы добавить новое ограничение к просмотру на основе мультипликатора я хотел. Это, конечно, привело к ошибке:

When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled.

Мой вопрос, поэтому, если я могу лечить constant свойство подобно multiplier собственности. Однако мой страх в этом заключается в том, что если я установил constant для ширины первого детского вида, он не обновил бы свою ширину, когда телефон вращается.

Есть ли лучшее решение для всего этого?

ответ

1

Во-первых, в вашем вопросе вы использовали IB, но вы, казалось, предлагали, что каждый раз, когда вы переходите к контроллеру представления, может появляться различное количество просмотров, поэтому я решил программно создать NSLayoutConstraint.

Во-вторых, мое решение в порядке, если вы не собираетесь изменять количество просмотров, пока вы были на контроллере. Если да, то это требует немного больше работы.

В контроллере представления:

var viewWidthConstraints : [NSLayoutConstraint] = [] 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let numberOfViews = 3 
    var previousView: UIView = self.view 

    for i in 0..<numberOfImages { 
     let myView = UIView() 
     myView.setTranslatesAutoresizingMaskIntoConstraints(false) 
     myView.backgroundColor = UIColor.grayColor().colorWithAlphaComponent(CGFloat(i) * (1/CGFloat(numberOfImages)) + 0.1) 
     self.view.addSubview(myView) 

     let heightConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", 
           options: .DirectionLeadingToTrailing, 
           metrics: nil, 
           views: ["view" : myView]) 

     let widthConstraint = NSLayoutConstraint(item: myView, 
           attribute: .Width, 
           relatedBy: .Equal, 
           toItem: nil, 
           attribute: .NotAnAttribute, 
           multiplier: 1.0, 
           constant: self.view.frame.width/CGFloat(numberOfImages)) 

     let attribute: NSLayoutAttribute = (i == 0) ? .Left : .Right 
     let leftConstraint = NSLayoutConstraint(item: myView, 
      attribute: .Left, 
      relatedBy: .Equal, 
      toItem: previousView, 
      attribute: attribute, 
      multiplier: 1.0, 
      constant: 0.0) 

     self.view.addConstraints(heightConstraint) 
     self.view.addConstraint(leftConstraint) 
     myView.addConstraint(widthConstraint) 

     viewWidthConstraints.append(widthConstraint) 

     previousView = myView 
    } 
} 

func updateWidthConstraints() { 
    if viewWidthConstraints.count > 0 { 
     let width = self.view.frame.width/CGFloat(viewWidthConstraints.count) 

     for constraint in viewWidthConstraints { 
      constraint.constant = width 
     } 
    } 
} 

override func viewWillLayoutSubviews() { 
    updateWidthConstraints() 
} 

В viewDidLoad вы добавляете UIView S к виду и установить их ограничения. Вертикальное ограничение, которое вы можете изменить, чтобы сделать UIView s, отображается под вашим UIImageView. И изменить numberOfViews, чтобы увеличить или уменьшить количество просмотров.

Затем в viewWillLayoutSubviews вы обновляете ширину каждого вида, используя ограничение ширины. Это гарантирует, что если устройство повернуто, каждый вид занимает нужную пропорцию экрана.

Это то, что похоже на горизонтальную ориентацию.

enter image description here

и вертикальной ориентации.

enter image description here

+0

Ничего себе, извините за поздний отклик. Это хорошо работает, однако я не могу поместить представления в представление контейнера, которое не охватывает весь экран. Под этим я подразумеваю, что если я установил 'previousView' в пользовательское представление, у которого есть левое и правое ограничение для его родителя 20px, произойдет следующее: http://i.imgur.com/rV8ubou.png – Charlie

Смежные вопросы