iOS UIStackView 使用技巧:添加彈簧和固定長度

UIStackView 類提供了一個高效的接口用于平鋪一行或一列的視圖組合。Stack視圖管理著所有在它的 arrangedSubviews 屬性中的視圖的布局。這些視圖根據(jù)它們在 arrangedSubviews 數(shù)組中的順序沿著 Stack 視圖的軸向排列。
簡而言之,即UIStackView,就是一個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, // 按照第一個子視圖的文字的第一行對齊,同時保證高度最大的子視圖底部對齊(只在axis為水平方向有效)
UIStackViewAlignmentCenter,//子視圖居中對齊
UIStackViewAlignmentTrailing,//子視圖右對齊(axis為垂直方向而言)
UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,//子視圖底部對齊(axis為水平方向而言)
UIStackViewAlignmentLastBaseline, // 按照最后一個子視圖的文字的最后一行對齊,同時保證高度最大的子視圖頂部對齊(只在axis為水平方向有效)
  • distribution:設(shè)置軸方向上子視圖的分布比例(如果axis是水平方向,也即設(shè)置子視圖的寬度,如果axis是垂直方向,則是設(shè)置子視圖的高度)
UIStackViewDistributionFill = 0, 填滿,不符合則按優(yōu)先級壓縮或拉伸控件
UIStackViewDistributionFillEqually, 子控件等寬(高)
UIStackViewDistributionFillProportionally, 根據(jù)每個子視圖里面內(nèi)容的尺寸來進行填充操作
UIStackViewDistributionEqualSpacing, 保證間距相等
UIStackViewDistributionEqualCentering, 保證每個子視圖中心直接的間距相等
  • spacing:該屬性控制子視圖之間的間隔大小,在distribution前三個屬性值設(shè)置的情況下,子視圖之間是沒有間隔,我們可以通過spacing屬性顯式的設(shè)置

2、distribution 各類模式

  • UIStackViewDistributionFill:填滿
    將arrangedSubviews填充滿整個StackView,他們之間的間隙等于spacing大小。如果減去所有的spacing,所有arrangedSubview的固有尺寸(intrinsicContentSize)之和不能填滿StackView,那么就按照Hugging的優(yōu)先級將其拉伸。反之,如果超出StackView的尺寸則按CompressionResistance的優(yōu)先級壓縮。如果優(yōu)先級相同,就按排列順序來拉伸或壓縮。
  • UIStackViewDistributionFillEqually:子控件等寬(高)
    每個arrangedSubview沿axis方向的長度相等,等于StackView沿axis長度減去spacing之和除以arrangedSubviews個數(shù)。
    鋪滿后如果是垂直排列所有的子視圖高度相等,如果是水平排列所有的子視圖寬度相等。
  • UIStackViewDistributionFillProportionally:按比例分配剩余空間
    根據(jù)每個子視圖里面內(nèi)容的尺寸來進行填充操作。
    根據(jù)arrangedSubview的intrinsicContentSize(原本尺寸),將StackView沿axis方向的長度減去spacing之和按比例分配給arrangedSubviews。
  • UIStackViewDistributionEqualSpacing:保證間距相等
    先按arrangedSubviews的intrinsicContentSize(原本尺寸)布局,然后余下的空間均分為spacing,如果spacing小于StackView設(shè)置的spacing,則按照CompressionResistance的優(yōu)先級來壓縮arrangedSubviews。
  • UIStackViewDistributionEqualCentering:中點之間等距離
    令arrangedSubviews的中心點之間的距離相等,且spacing大于等于StackView設(shè)置的spacing(每兩個arrangedSubview之間的spacing可能不相等)。如果spacing小于StackView設(shè)置的spacing,則按照CompressionResistance的優(yōu)先級來壓縮arrangedSubviews。

3、使用技巧

3.1> 善用嵌套

只要嵌套好UIStackView,就可以用很少的約束達到自動布局界面的目的。

3.2> 增量排版

如果排版比較復(fù)雜,不建議使用系統(tǒng)的 spacing 屬性,可以生成透明視圖來占位,約束視圖大小就可以達到控制子視圖間距的效果。

  • 固定長度:利用約束透明視圖的寬(高)度實現(xiàn)。
  • 彈簧:利用約束透明視圖的優(yōu)先級來實現(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

可以定制各個子控件后面的間距,但使用起來需要考慮版本適配的問題。

/* 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));
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容