An alternative to iOS Auto Layout
Stretch is a per-subview property. It has a few roles in WeView. Put simply, subviews can “stretch” to receive extra space in their layout.
There are separate horizontal and vertical stretch properties. That is, a subview may stretch horizontally but not vertically or vice versa.
Stretch can effect measurement, ie. a WeView with subviews that can stretch may report a larger size, since the WeView can grow to occupy the available space.
Stretch can also effect arrangement, both in terms of cell size (the cell of a subview that can stretch will grow to occupy extra space in its superview’s bounds) and subview size (a subview that can stretch will grow to fill its cell).
Here we set one UILabel to vertically stretch. Since it stretches vertically in a horizontal layout, its stretch does not effect the layout of the other subviews.
The stretch affects the vertical size of the subviews’s layout cell (See: Layout Model), and the subview stretches vertically to fill its layout cell.
Here we set one UILabel to horizontally stretch. Since it stretches horizontally in a horizontal layout, its stretch does effect the layout of the other subviews.
Again, the subview’s horizontal stretch affects the size of its layout cell.
When more than one subview stretches horizontally in a horizontal layout, they share any extra space in the layout equally between them.
Note that they do not have the same width; they each receive an equal amount of extra space in addition to their desired size. If we wanted them to have the same width we would a) make sure they had the same stretch weight and b) call [UIView setIgnoreDesiredSize] on both views, so that their sizes were based purely on their stretch weight and not on their desired size.
Usually it is sufficient to set whether or not subviews stretch. However, we can also control how they stretch by setting their stretch weight. Extra space is divided between subviews that can stretch in proportion to their relative stretch weights.
In this example, the second label has an hStretchWeight of 1.0 and the first label is shown with hStretchWeights of 0.0, 1.0, 2.0, 3.0 and 4.0. Extra space is divided between the stretching subview in proportion to their weights.
[UIView setHStretches] is equivalent to [UIView setHStretchWeight:1.f], since the default stretch weight is 1.0.
The UIView+WeView category adds two stretch-related properties to all UIViews:
- (UIView *)setHStretchWeight:(CGFloat)value;
- (UIView *)setVStretchWeight:(CGFloat)value;
The UIView+WeView category also adds a few convenience accessors:
- (UIView *)setHStretches; // A convenience accessor that sets hStretchWeight = 1.f.
- (UIView *)setVStretches; // A convenience accessor that sets vStretchWeight = 1.f.
- (UIView *)setStretches; // A convenience accessor that sets hStretchWeight = 1.f and vStretchWeight = 1.f.
Typically, we just want to indicate which subviews stretch and which don’t. These convenience accessors set stretch to a default non-zero value.
As noted above, usually layouts will begin by laying out their subviews at their desired sizes and then distribute any remaining extra space between stretching subviews in proportion to their relative stretch weights. Sometimes it is convenient to ignore the desired size of subviews.
It this example, we have a UILabel and a UIScrollView in a vertical layout. The UIScrollView contains a UIImageView with an image much larger than the available space. The title’s height should reflect it’s desired size and the UIScrollView should get the rest of the height, regardless of its desired size. We therefore invoke [UIView setIgnoreDesiredSize] on the UIScrollView.
The Grid Layout supports a number of advanced features, such as stretch of spacing and margins. See the Grid Layout section of the tutorial.
Next: Tutorial 12: Discussion