Relearn AutoLayout (2) — UIStackView
The focus of the StackView
- UIStackView is just a container!! (It doesn’t
intrinsic content size
) - UIStackView is different
distributions
Properties work differently!! (Fill & fillEqual behave differently!) - Element added to UIStackViewMust behave
Intrinsic Content Size
ScrollView is nested StackView
A few of the keys:
- The ScrollView Anchor configures the ViewPort of the ScrollView
- The StackView Anchor inside the ScrollView also needs to Pin to the ScrollView size
- Row must exist in StackView
IntrinsicContentSize
- Row can enforce horizontal constraint Overrides
IntrinsicContent.width
{ func setupViews() { navigationItem.title = "Scrollable" let stackView = makeStackView(withOrientation: .vertical) let scrollView = makeScrollView() // scrollView is a stackView. view.addSubview(scrollView) for _ in 1... 30 {let row = RowView () stackView. AddArrangedSubview (row) / / control internal control constraints, external view, To stretch the width row. WidthAnchor. The constraint (equalTo: scrollView.widthAnchor).isActive = true } // Pinning to the sides of view stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true // Pinning scrollview scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true scrollView.bottomAnchor.constraint(equalTo: View. SafeAreaLayoutGuide. BottomAnchor). IsActive = true}} / / custom raow class RowView: UIView {override init (frame: CGRect) { super.init(frame: frame) setupViews() } required init? (coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func setupViews() { let titleLabel = makeLabel(withText: "Gapless Playback") let onOffSwith = makeSwitch(isOn: true) addSubview(titleLabel) addSubview(onOffSwith) // titleLabel titleLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true // offSwitch onOffSwith.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true onOffSwith.centerYAnchor.constraint(equalTo: Titlelabel.centeryanchor). IsActive = true} Intrinsic ContentSize -> for StackView! override var intrinsicContentSize: CGSize { return CGSize(width: 200, height: 31) } }Copy the code
Summary of StackView usage
-
If we Pin a StackView to a side with certain margins, notice how the contents of the StackView change (definitely different from the result of the Center StackView).
-
Objects managed by UIStackView must have Intrinsic sizes, so if you want to introduce some custom objects, override the IntrinsicContentSize method.
-
On the axis, all distribution types except stackView.distribution =.fillequally, Stackview uses arrangedViews intrinsicContentSize to calculate stack axis dimensions!! (Presumably we can calculate the axial length of the StackView with no other external constraints).
fillEqually
Makes all arrangeViews have the same size constraint on the axis!!
-
On the cross axis, stackView.alignment =.fill is the only alignment type, The StackView is also the size of its interfacing axes using the Layout Views intrinsicContentSize (thus we can presumably calculate the length of the interfacing axes of the StackView with no other external constraints).
.alignment = .fill
, the Stack view will stretch all its managed views to match the maximum inherent size of their crossover axes
-
In addition to managing valid contents, stackSpacerViews can also be added to Anchor to help modify the spacing between different arrangeSubviews!!
-
When using StackView, there are two common ways to stretch the StackView on the cross axis so that the Anchor of required Priority can Override the Intrinsic Size constraint:
- Set widthAnchor directly to StackView
- Set an Anchor with cross axis to ArrangeView, the Anchor needs to be on the outside View.
-
The design of a nested StackView must incorporate CRPCHP!!!! from the inside out For details, please refer to Apple’s official Auto Layout CookBook
Here is an example of StackSpacerView:
Create a spacerView!! Public func makeSpacerView(height: CGFloat? = nil) -> UIView { let spacerView = UIView(frame: Zero) / / increase its heightAchor and breakable () if the let height height = {spacerView. HeightAnchor. The constraint (equalToConstant: height).setActiveBreakable() } spacerView.translatesAutoresizingMaskIntoConstraints = false return spacerView } // Public Extension NSLayoutConstraint {@objc func setActiveBreakable(priority: priority) public Extension NSLayoutConstraint {@objc func setActiveBreakable(priority: priority) UILayoutPriority = UILayoutPriority(900)) { self.priority = priority isActive = true } }Copy the code
reference
- www.cnblogs.com/tieria/p/45…
- www.jianshu.com/p/633e238b2…
- Github.com/HChong3210/…