級別: ★☆☆☆☆
標簽:「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中獲取。