UIStackView 類提供了一個(gè)高效的接口用于平鋪一行或一列的視圖組合。Stack視圖管理著所有在它的 arrangedSubviews 屬性中的視圖的布局膝昆。這些視圖根據(jù)它們在 arrangedSubviews 數(shù)組中的順序沿著 Stack 視圖的軸向排列组贺。
簡而言之凸舵,即UIStackView,就是一個(gè)ContainerView失尖,可以沿橫向或縱向按照一定的規(guī)則布局內(nèi)部的子View啊奄。
1、四大屬性
UIStackView主要包括了四大屬性:axis掀潮、alignment菇夸、distribution、spacing仪吧。
- axis:布局方向
UILayoutConstraintAxisHorizontal = 0,//水平
UILayoutConstraintAxisVertical = 1//垂直
- alignment:非軸方向子視圖的對齊方式
UIStackViewAlignmentFill,//子視圖填充StackView
UIStackViewAlignmentLeading,//子視圖左對齊(axis為垂直方向而言)
UIStackViewAlignmentTop = UIStackViewAlignmentLeading,//子視圖頂部對齊(axis為水平方向而言)
UIStackViewAlignmentFirstBaseline, // 按照第一個(gè)子視圖的文字的第一行對齊庄新,同時(shí)保證高度最大的子視圖底部對齊(只在axis為水平方向有效)
UIStackViewAlignmentCenter,//子視圖居中對齊
UIStackViewAlignmentTrailing,//子視圖右對齊(axis為垂直方向而言)
UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,//子視圖底部對齊(axis為水平方向而言)
UIStackViewAlignmentLastBaseline, // 按照最后一個(gè)子視圖的文字的最后一行對齊,同時(shí)保證高度最大的子視圖頂部對齊(只在axis為水平方向有效)
- distribution:設(shè)置軸方向上子視圖的分布比例(如果axis是水平方向,也即設(shè)置子視圖的寬度择诈,如果axis是垂直方向械蹋,則是設(shè)置子視圖的高度)
UIStackViewDistributionFill = 0, 填滿,不符合則按優(yōu)先級壓縮或拉伸控件
UIStackViewDistributionFillEqually, 子控件等寬(高)
UIStackViewDistributionFillProportionally, 根據(jù)每個(gè)子視圖里面內(nèi)容的尺寸來進(jìn)行填充操作
UIStackViewDistributionEqualSpacing, 保證間距相等
UIStackViewDistributionEqualCentering, 保證每個(gè)子視圖中心直接的間距相等
- spacing:該屬性控制子視圖之間的間隔大小羞芍,在distribution前三個(gè)屬性值設(shè)置的情況下哗戈,子視圖之間是沒有間隔,我們可以通過spacing屬性顯式的設(shè)置
2涩金、distribution 各類模式
- UIStackViewDistributionFill:填滿
將arrangedSubviews填充滿整個(gè)StackView谱醇,他們之間的間隙等于spacing大小暇仲。如果減去所有的spacing步做,所有arrangedSubview的固有尺寸(intrinsicContentSize)之和不能填滿StackView,那么就按照Hugging的優(yōu)先級將其拉伸奈附。反之全度,如果超出StackView的尺寸則按CompressionResistance的優(yōu)先級壓縮。如果優(yōu)先級相同斥滤,就按排列順序來拉伸或壓縮将鸵。
- UIStackViewDistributionFillEqually:子控件等寬(高)
每個(gè)arrangedSubview沿axis方向的長度相等,等于StackView沿axis長度減去spacing之和除以arrangedSubviews個(gè)數(shù)佑颇。
鋪滿后如果是垂直排列所有的子視圖高度相等顶掉,如果是水平排列所有的子視圖寬度相等。
- UIStackViewDistributionFillProportionally:按比例分配剩余空間
根據(jù)每個(gè)子視圖里面內(nèi)容的尺寸來進(jìn)行填充操作挑胸。
根據(jù)arrangedSubview的intrinsicContentSize(原本尺寸)痒筒,將StackView沿axis方向的長度減去spacing之和按比例分配給arrangedSubviews。
- UIStackViewDistributionEqualSpacing:保證間距相等
先按arrangedSubviews的intrinsicContentSize(原本尺寸)布局茬贵,然后余下的空間均分為spacing簿透,如果spacing小于StackView設(shè)置的spacing,則按照CompressionResistance的優(yōu)先級來壓縮arrangedSubviews解藻。
- UIStackViewDistributionEqualCentering:中點(diǎn)之間等距離
令arrangedSubviews的中心點(diǎn)之間的距離相等老充,且spacing大于等于StackView設(shè)置的spacing(每兩個(gè)arrangedSubview之間的spacing可能不相等)。如果spacing小于StackView設(shè)置的spacing螟左,則按照CompressionResistance的優(yōu)先級來壓縮arrangedSubviews啡浊。
3、使用技巧
3.1> 善用嵌套
只要嵌套好UIStackView胶背,就可以用很少的約束達(dá)到自動布局界面的目的巷嚣。
3.2> 增量排版
如果排版比較復(fù)雜,不建議使用系統(tǒng)的 spacing 屬性奄妨,可以生成透明視圖來占位涂籽,約束視圖大小就可以達(dá)到控制子視圖間距的效果。
- 固定長度:利用約束透明視圖的寬(高)度實(shí)現(xiàn)砸抛。
- 彈簧:利用約束透明視圖的優(yōu)先級來實(shí)現(xiàn)评雌。
-
如果兩邊都使用彈簧物臂,需要再將彈簧約束為等寬(高)
-
如果兩邊都使用彈簧物臂,需要再將彈簧約束為等寬(高)
// 占位視圖宏定義
#define StackFixed(w, h) \
^{\
UIView *view = UIView.new;\
[view mas_makeConstraints:^(MASConstraintMaker *make) {\
if (w > 0) make.width.mas_equalTo(w);\
if (h > 0) make.height.mas_equalTo(h);\
}];\
return view;\
}()
// 彈簧宏定義
#define StackSpring(axis) \
^{\
UIView *view = UIView.new; \
[view mas_makeConstraints:^(MASConstraintMaker *make) {\
if (axis == UILayoutConstraintAxisHorizontal) {\
make.width.mas_equalTo(1000).priorityLow();\
} else {\
make.height.mas_equalTo(1000).priorityLow();\
}\
}];\
return view;\
}()
Demo地址:StackViewDemo
iOS11 新增api
可以定制各個(gè)子控件后面的間距券册,但使用起來需要考慮版本適配的問題。
/* Set and get custom spacing after a view.
This custom spacing takes precedence over any other value that might otherwise be used
for the space following the arranged subview.
Defaults to UIStackViewSpacingUseDefault (Swift: UIStackView.spacingUseDefault), where
resolved value will match the spacing property.
You may also set the custom spacing to UIStackViewSpacingUseSystem (Swift: UIStackView.spacingUseSystem),
where the resolved value will match the system-defined value for the space to the neighboring view,
independent of the spacing property.
Maintained when the arranged subview changes position in the stack view, but not after it
is removed from the arrangedSubviews list.
Ignored if arrangedSubview is not actually an arranged subview.
*/
- (void)setCustomSpacing:(CGFloat)spacing afterView:(UIView *)arrangedSubview API_AVAILABLE(ios(11.0),tvos(11.0));
- (CGFloat)customSpacingAfterView:(UIView *)arrangedSubview API_AVAILABLE(ios(11.0),tvos(11.0));