iOS 常用布局方式之StackView

級別: ★☆☆☆☆
標簽:「iOS UIStackView」「iOS 自動布局」「StackView」
作者: Xs·H
審校: QiShare團隊


沐靈洛 線下分享iOS UIButton根據內容自動布局時,有和前端同學討論到iOS的常用布局方式。討論過程十分熱鬧,不容易記錄,但作者認為討論結果有必要記錄一下,希望能幫助到一些同學。
作者將iOS常用布局方式歸納為Frame、Autoresizing、Constraint、StackView和Masonry五種,并將逐一介紹。
本篇文章介紹StackView。

UIStackView是UIKit在iOS9中新增的視圖類。它可以被理解成一個容器,能夠對添加到容器中的視圖按照行或列進行布局。作者以之前文章中提到的4分圖為例,結合storyboard,可以很快速地實現效果。如下圖。

如上圖,作者在沒有編碼的情況下使用UIStackView快速構建了一個4分圖的布局效果,甚至沒有對4分圖添加Constraint。可見UIStackView在自動布局方便有著強大的能力和效率。當然UIStackView也允許開發者進行編碼,使用相關屬性實現需求效果。使用UIStackView實現4分圖效果的代碼如下。

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    UIView *subView1 = [[UIView alloc] initWithFrame:CGRectZero];
    subView1.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:.6];
    
    UIView *subView2 = [[UIView alloc] initWithFrame:CGRectZero];
    subView2.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:.6];
    
    UIView *subView3 = [[UIView alloc] initWithFrame:CGRectZero];
    subView3.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:.6];
    
    UIView *subView4 = [[UIView alloc] initWithFrame:CGRectZero];
    subView4.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:.6];
    
    
    UIStackView *subStackView1 = [[UIStackView alloc] initWithFrame:CGRectZero];
    subStackView1.spacing = 10.0;
    subStackView1.alignment = UIStackViewAlignmentFill;
    subStackView1.axis = UILayoutConstraintAxisHorizontal;
    subStackView1.distribution = UIStackViewDistributionFillEqually;
    [subStackView1 addArrangedSubview:subView1];
    [subStackView1 addArrangedSubview:subView2];
    
    UIStackView *subStackView2 = [[UIStackView alloc] initWithFrame:CGRectZero];
    subStackView2.spacing = 10.0;
    subStackView2.alignment = UIStackViewAlignmentFill;
    subStackView2.axis = UILayoutConstraintAxisHorizontal;
    subStackView2.distribution = UIStackViewDistributionFillEqually;
    [subStackView2 addArrangedSubview:subView3];
    [subStackView2 addArrangedSubview:subView4];
    
    
    UIStackView *stackView = [[UIStackView alloc] initWithFrame:self.view.bounds];
    stackView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    stackView.spacing = 10.0;
    stackView.alignment = UIStackViewAlignmentFill;
    stackView.axis = UILayoutConstraintAxisVertical;
    stackView.distribution = UIStackViewDistributionFillEqually;
    [stackView addArrangedSubview:subStackView1];
    [stackView addArrangedSubview:subStackView2];
    [self.view addSubview:stackView];
}

在上述代碼中,作者將4個subView分別放到了兩個subStackView中,并實現了subView在subStackView中橫向等寬排列,然后將兩個subStackView放到了stackView中,并實現了subStackView在stackView中豎向等高排列。這里,要重點介紹一下實現這些效果的屬性。

  • axis

axis是UILayoutConstraintAxis類型的枚舉變量,負責設置stackView排列方向。

/* A stack with a horizontal axis is a row of arrangedSubviews,
and a stack with a vertical axis is a column of arrangedSubviews.
 */
@property(nonatomic) UILayoutConstraintAxis axis;
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
    UILayoutConstraintAxisHorizontal = 0,
    UILayoutConstraintAxisVertical = 1
};
  • alignment

alignment是UIStackViewAlignment類型的枚舉變量,負責設置stackView子視圖的對齊方式。

/* The layout of the arrangedSubviews transverse to the axis;
 e.g., leading/trailing edges in a vertical stack
 */
@property(nonatomic) UIStackViewAlignment alignment;
/* Alignment—the layout transverse to the stacking axis.
 */
typedef NS_ENUM(NSInteger, UIStackViewAlignment) {
    /* Align the leading and trailing edges of vertically stacked items
     or the top and bottom edges of horizontally stacked items tightly to the container.
     */
    UIStackViewAlignmentFill,//!< 子視圖填充
    
    /* Align the leading edges of vertically stacked items
     or the top edges of horizontally stacked items tightly to the relevant edge
     of the container
     */
    UIStackViewAlignmentLeading,//!< 豎直排列時,子視圖左對齊
    UIStackViewAlignmentTop = UIStackViewAlignmentLeading,//!< 水平排列時,子視圖上對齊
    UIStackViewAlignmentFirstBaseline, // Valid for horizontal axis only //!< 水平排列時,子視圖按照首個子視圖的首行文字對齊
    
    /* Center the items in a vertical stack horizontally
     or the items in a horizontal stack vertically
     */
    UIStackViewAlignmentCenter,//!< 居中對齊
    
    /* Align the trailing edges of vertically stacked items
     or the bottom edges of horizontally stacked items tightly to the relevant
     edge of the container
     */
    UIStackViewAlignmentTrailing,//!< 豎直排列時,子視圖右對齊
    UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,//!< 水平排列時,子視圖下對齊
    UIStackViewAlignmentLastBaseline, // Valid for horizontal axis only //!< 水平排列時,子視圖按照最后一個子視圖的末行文字對齊
} NS_ENUM_AVAILABLE_IOS(9_0);
  • distribution

distribution是UIStackViewDistribution類型的枚舉變量,負責設置stackView子視圖的寬度或高度布局。

/* The layout of the arrangedSubviews along the axis
 */
@property(nonatomic) UIStackViewDistribution distribution;
/* Distribution—the layout along the stacking axis.
 
 All UIStackViewDistribution enum values fit first and last arranged subviews tightly to the container,
 and except for UIStackViewDistributionFillEqually, fit all items to intrinsicContentSize when possible.
 */
typedef NS_ENUM(NSInteger, UIStackViewDistribution) {
    
    /* When items do not fit (overflow) or fill (underflow) the space available
     adjustments occur according to compressionResistance or hugging
     priorities of items, or when that is ambiguous, according to arrangement
     order.
     */
    UIStackViewDistributionFill = 0, //!< 子視圖填充,多個視圖時以最后一個視圖填充
    
    /* Items are all the same size.
     When space allows, this will be the size of the item with the largest
     intrinsicContentSize (along the axis of the stack).
     Overflow or underflow adjustments are distributed equally among the items.
     */
    UIStackViewDistributionFillEqually,//!< 子視圖等寬或等高填充
    
    /* Overflow or underflow adjustments are distributed among the items proportional
     to their intrinsicContentSizes.
     */
    UIStackViewDistributionFillProportionally,//!< 子視圖按比例填充
    
    /* Additional underflow spacing is divided equally in the spaces between the items.
     Overflow squeezing is controlled by compressionResistance priorities followed by
     arrangement order.
     */
    UIStackViewDistributionEqualSpacing,//!< 子視圖等間距填充
    
    /* Equal center-to-center spacing of the items is maintained as much
     as possible while still maintaining a minimum edge-to-edge spacing within the
     allowed area.
        Additional underflow spacing is divided equally in the spacing. Overflow 
     squeezing is distributed first according to compressionResistance priorities 
     of items, then according to subview order while maintaining the configured 
     (edge-to-edge) spacing as a minimum.
     */
    UIStackViewDistributionEqualCentering,//!< 子視圖等中點填充
} NS_ENUM_AVAILABLE_IOS(9_0);
  • spacing

spacing是CGFloat類型的變量,負責設置stackView子視圖之間的間距。

/* Spacing between adjacent edges of arrangedSubviews.
 Used as a strict spacing for the Fill distributions, and
 as a minimum spacing for the EqualCentering and EqualSpacing
 distributions. Use negative values to allow overlap.
 
 On iOS 11.0 or later, use UIStackViewSpacingUseSystem (Swift: UIStackView.spacingUseSystem) 
 to get a system standard spacing value. Setting spacing to UIStackViewSpacingUseDefault 
 (Swift: UIStackView.spacingUseDefault) will result in a spacing of 0.
 
 System spacing between views depends on the views involved, and may vary across the 
 stack view.
 
 In vertical stack views with baselineRelativeArrangement == YES, the spacing between 
 text-containing views (such as UILabels) will depend on the fonts involved.
 */
@property(nonatomic) CGFloat spacing;

綜上,UIStackView可謂是iOS的布局神器,在cell等多見布局需求的場景中能起到重要的作用。關于本篇文章中的代碼部分,可以從QiLayoutDemo中獲取。


推薦文章:
iOS UIButton根據內容自動布局
iOS 指定初始化方法
UIView中的hitTest方法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容