如何使用NSLayoutConstraint可视格式水平对齐UIView的3个子视图

时间:2013-09-17 20:06:51

标签: ios autolayout nslayoutconstraint

我有以下设置:

  1. 尺寸为(40,40)的UIView
  2. 此视图的3个子视图,每个都有框架(0,0,40,40)
  3. 现在我希望此设置始终保持以下约束:

    H:| -10- [V1] -10- [V2] -10- [V3] -10- |

    这意味着在superview的整个生命周期中存在以下期望的行为:

    1. 设置约束后,视图应立即自动布局,如上所示。
    2. 由于superview本身仅为(40,40),因此应自动调整大小以使布局成为可能。
    3. 从那时起,更改任何子视图的宽度应该再次布局视图,以便它们仍然坚持布局格式。
    4. 到目前为止我的方法是这样的:

      - (id)init
      {
          self = [super initWithFrame:CGRectMake(0, 0, 40, 40)];
          if (self) {
              self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
              self.v1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
              self.v2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
              self.v3 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
      
              [self addSubview:self.v1];
              [self addSubview:self.v2];
              [self addSubview:self.v3];
              NSDictionary *views = @{@"v1" : self.v1, @"v2" : self.v2, @"v3" : self.v3};
              [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[v1]-10-[v2]-10-[v3]-10-|" options:0 metrics:@{@"10":@10} views:views]];
              [self layoutIfNeeded];
          }
      }
      

      但是我得到了冲突的约束消息:

      (
          "<NSLayoutConstraint:0xed9f040 H:|-(10)-[UIView:0xed9ad30]   (Names: '|':MyView:0xed9a040 )>",
          "<NSLayoutConstraint:0xed9f270 H:[UIView:0xed9ad30]-(10)-[UIView:0xed9c370]>",
          "<NSAutoresizingMaskLayoutConstraint:0xeda3770 h=&&& v=-&- UIView:0xed9c370.midX == 0.5*MyView:0xed9a040.width>",
          "<NSAutoresizingMaskLayoutConstraint:0xeda37a0 h=&&& v=-&- UIView:0xed9c370.width == MyView:0xed9a040.width>"
      )
      
      Will attempt to recover by breaking constraint 
      <NSLayoutConstraint:0xed9f270 H:[UIView:0xed9ad30]-(10)-[UIView:0xed9c370]>
      

      我的猜测是,它与superview无法调整大小有关。但我总体上对此感到困惑。有谁知道我做错了什么?

1 个答案:

答案 0 :(得分:3)

您希望确保以编程方式创建的视图将translatesAutoresizingMaskIntoConstraints设置为NO,例如:

self.v1.translatesAutoresizingMaskIntoConstraints = NO;
self.v2.translatesAutoresizingMaskIntoConstraints = NO;
self.v3.translatesAutoresizingMaskIntoConstraints = NO;

如果您希望这三个子视图的宽度相同,间隔10,则可以使用水平VFL:

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[v1]-10-[v2(==v1)]-10-[v3(==v1)]-10-|" options:0 metrics:nil views:views]];

显然,每个子视图之间的间隔为10个点,超级视图必须宽于40个点。例如,如果超级视图是100点宽,一旦你将子视图之间的10个点空间分解出来(为子视图留下60个宽度点,它们本身),约束系统会使每个子视图宽20个点。

而且,如果你希望那些高40点,你可以定义垂直约束(以及定义你想要它们超级视图顶部的距离):

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v1(40)]" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v2(40)]" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v3(40)]" options:0 metrics:nil views:views]];

这定义了它们与超视图的偏移量为零,但高度为40点。

而且,如果您已根据约束定义了视图,则无需使用initWithFrame,而只需使用init。使用自动布局时,通常不会为任何内容指定frame,而是让约束条件决定大小。