UIView 等寬或等高排列
在 UI 開發中,時不時需要把幾個按鈕或者 UILabel 并排著排列,在以前用坐標系布局時都是靠算,很麻煩還容易出錯,現在 Autolayout 這么方便,能不能使用 Autolayout 完成這個布局工作呢?試試看。
Autolayout 的布局規則是寫 View 與 View 間的相對關系,我們來分析一下,如果要使 3 個 View 在一個容器 View 中均分需要滿足哪些條件。
- 最左邊 View 到父 View 一定邊距
- 所有 View 寬度相等
- 一個 View 到下一個 View 有一定邊距
- 最右邊 View 到父 View 一定邊距
如果想要這些 View 在容器中完全均分,上述的邊距都為 0 即可。
按照上面的想法來實踐下,以下代碼中的幾個方法是對 NSLayoutConstraint 實例方法 constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: 的簡單封裝,字面意思,詳情實現見 UIView+CPYLayout.m
以下方法為 NSArray 的一個擴展,假設我們將所需要布局的 View 放在了一個數組中,并都 addSubview 到了一個容器 View 中。
UIView *container=[[UIView alloc]init];
[self.view addSubview:container];
container.backgroundColor =[UIColor redColor];
[[[[container cpy_alignYToSuperview]cpy_toHeight:100]cpy_leftToSuperview:0]cpy_rightToSuperview:0];
NSMutableArray *arr = [NSMutableArray array];
for (int i = 0; i < 8; i++) {
UIView *v = [[UIView alloc]init];
v.backgroundColor = [UIColor blueColor];
[container addSubview:v];
[arr addObject:v];
[v cpy_constraintEqualTo:NSLayoutAttributeWidth toView:v toAttribute:NSLayoutAttributeHeight constant:0];
}
[arr cpy_flexibleWidthWithMargin:10 spacing:10];
@implementationNSArray (cpy_layout)
- (void)cpy_flexibleWidthWithMargin:(CGFloat)marginspacing:(CGFloat)spacing {
for (NSInteger i = 0; i < self.count;i++) {
UIView *tmp = self[i];
if(i ==0) {
// 設置第一 View 到父 View 的左邊距
[tmp cpy_leftToSuperView:margin];
}
if (tmp == self.lastObject) {
// 最后一個,設置到父 View 右邊距
[tmp cpy_rightToSuperView:margin];
}
else {
// 不是最后一個,設置寬度相等和到下一個 View 的間距
UIView *next = self[i + 1];
[[tmp cpy_constraintEqualTo:NSLayoutAttributeWidth toView:next toAttribute:NSLayoutAttributeWidth constant:0]cpy_rightToLeftToView:nextconstant:spacing];
}
// 設置居中
[tmp cpy_alignYToSuperView];
}
}
@end
效果如下:
也可以不設置容器 View 的寬度或者邊距約束,讓它根據子 View 的布局后的大小自行調整大小,但是這樣的話,就需要設置子 View 到容器的邊距約束,不然沒辦法完成布局。代碼如下:
UIView *container=[[UIView alloc]init];
[self.view addSubview:container];
container.backgroundColor =[UIColor redColor];
// 只設置了居中,沒有設置邊距和寬高約束
[container cpy_centerToSuperview];
NSMutableArray *arr = [NSMutableArray array];
for (int i = 0; i < 8; i++) {
UIView *v = [[UIView alloc]init];
v.backgroundColor = [UIColor blueColor];
[container addSubview:v];
[arr addObject:v];
// 這里設置了寬度,和到父 View 的上下邊距
[[[v cpy_toWidth:20]cpy_topToSuperview:0]cpy_bottomToSuperview:0];
[v cpy_constraintEqualTo:NSLayoutAttributeWidth toView:v toAttribute:NSLayoutAttributeHeight constant:0];
}
// 這里會設置子 View 到父 View 的左右邊距
[arr cpy_flexibleWidthWithMargin:0 spacing:10];
這樣約束條件都滿足了,運行看一下效果:
同理,也可以垂直等高排列:
UIView *container=[[UIView alloc]init];
[self.view addSubview:container];
container.backgroundColor =[UIColor redColor];
[container cpy_centerToSuperview];
NSMutableArray *arr = [NSMutableArray array];
for (int i = 0; i < 8; i++) {
UIView *v = [[UIView alloc]init];
v.backgroundColor = [UIColor blueColor];
[container addSubview:v];
[arr addObject:v];
[[[v cpy_toWidth:20]cpy_leftToSuperview:0]cpy_rightToSuperview:0];
[v cpy_constraintEqualTo:NSLayoutAttributeWidth toView:v toAttribute:NSLayoutAttributeHeight constant:0];
}
[arr cpy_flexibleHeightWithMargin:0 spacing:5];
效果如下:
嗯,還不錯 :)
這樣就不用算一大堆坐標,只需要設置幾條約束就可以了,并且這樣如果需要添加或者去掉一個 View 也比較方便。
完整 Demo 見: https://github.com/cielpy/CPYFlexibleViewDemo
來自:https://imciel.com/2016/08/29/uiview-same-width-autolayout/