iOS 經常使用佈局方式之StackView

級別: ★☆☆☆☆
標籤:「iOS UIStackView」「iOS 自動佈局」「StackView」
做者: Xs·H
審校: QiShare團隊php


沐靈洛 線下分享iOS UIButton根據內容自動佈局時,有和前端同窗討論到iOS的經常使用佈局方式。討論過程十分熱鬧,不容易記錄,但做者認爲討論結果有必要記錄一下,但願能幫助到一些同窗。 做者將iOS經常使用佈局方式概括爲Frame、Autoresizing、Constraint、StackView和Masonry五種,並將逐一介紹。 本篇文章介紹StackView。前端

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

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

- (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中豎向等高排列。這裏,要重點介紹一下實現這些效果的屬性。bash

  • 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子視圖的對齊方式。ide

/* 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子視圖之間的間距。this

/* 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中獲取。編碼


小編微信:可加並拉入《QiShare技術交流羣》。

關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)

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

相關文章
相關標籤/搜索