1.Getting started
Understanding Auto Layout
External Changes
- The user resizes the window (OS X).
- The user enters or leaves Split View on an iPad (iOS).
- The device rotates (iOS).
- The active call and audio recording bars appear or disappear (iOS).
- You want to support different size classes.
- You want to support different screen sizes.
Internal Changes
- The content displayed by the app changes.
- The app supports internationalization.
- The app supports Dynamic Type (iOS).
You can programmatically lay out the user interface, you can use autoresizing masks to automate some of the responses to external change, or you can use Auto Layout.
[Additionally, autoresizing masks adapt only to external changes. They do not support internal changes.]
2.Auto Layout Without Constraints
UIStackView/NSStackView
[axis]: defines the stack view’s orientation, either vertical or horizontal.
[orientation] :defines the stack view’s orientation, either vertical or horizontal.
[distribution]:defines the layout of the views along the axis.
[alignment]:defines the layout of the views perpendicular to the stack view’s axis.
[spacing]:defines the space between adjacent views.
3.Anatomy of a Constraint
- Item 1. The first item in the equation—in this case, the red view. The item must be either a view or a layout guide
- Attribute 1. The attribute to be constrained on the first item—in this case, the red view’s leading edge.
- Relationship. The relationship between the left and right sides. The relationship can have one of three values: equal, greater than or equal, or less than or equal. In this case, the left and right side are equal.
- Multiplier. The value of attribute 2 is multiplied by this floating point number. In this case, the multiplier is 1.0.
- Item 2. The second item in the equation—in this case, the blue view. Unlike the first item, this can be left blank.
- Attribute 2. The attribute to be constrained on the second item—in this case, the blue view’s trailing edge. If the second item is left blank, this must be Not an Attribute.
- Constant. A constant, floating-point offset—in this case, 8.0. This value is added to the value of attribute 2.
Sample Equations
Equality, Not Assignment
Constraint Inequalities:
As soon as you start using inequalities, the two constraints per view per dimension rule breaks down. You can always replace a single equality relationship with two inequalities.
Constraint Priorities:
1。You can also create optional constraints. All constraints have a priority between 1 and 1000. Constraints with a priority of 1000 are required. All other constraints are optional.
2。When calculating solutions, Auto Layout attempts to satisfy all the constraints in priority order from highest to lowest. If it cannot satisfy an optional constraint, that constraint is skipped and it continues on to the next constraint.
3。Even if an optional constraint cannot be satisfied, it can still influence the layout. If there is any ambiguity in the layout after skipping the constraint, the system selects the solution that comes closest to the constraint. In this way, unsatisfied optional constraints act as a force pulling views towards them.
4。The greater-than-or-equal relationship could be required (priority of 1000), and the less-than-or-equal relationship has a lower priority (priority 250).
Intrinsic Content Size:
UIView and NSView --------> No intrinsic content size.
Sliders --------> Defines only the width (iOS).Defines the width, the height, or both—depending on the slider’s type (OS X).
Labels, buttons, switches, and text fields --------> Defines both the height and the width.
Text views and image views --------> Intrinsic content size can vary.
The intrinsic content size is based on the view’s current content. A label or button’s intrinsic content size is based on the amount of text shown and the font used. For other views, the intrinsic content size is even more complex. For example, an empty image view does not have an intrinsic content size. As soon as you add an image, though, its intrinsic content size is set to the image’s size.
A text view’s intrinsic content size varies depending on the content, on whether or not it has scrolling enabled, and on the other constraints applied to the view. For example, with scrolling enabled, the view does not have an intrinsic content size. With scrolling disabled, by default the view’s intrinsic content size is calculated based on the size of the text without any line wrapping. For example, if there are no returns in the text, it calculates the height and width needed to layout the content as a single line of text. If you add constraints to specify the view’s width, the intrinsic content size defines the height required to display the text given its width.
Auto Layout represents a view’s intrinsic content size using a pair of constraints for each dimension. The content hugging pulls the view inward so that it fits snugly around the content. The compression resistance pushes the view outward so that it does not clip the content.
// Compression Resistance
View.height >= 0.0 * NotAnAttribute + IntrinsicHeight
View.width >= 0.0 * NotAnAttribute + IntrinsicWidth
// Content Hugging
View.height <= 0.0 * NotAnAttribute + IntrinsicHeight
View.width <= 0.0 * NotAnAttribute + IntrinsicWidth
Each of these constraints can have its own priority. By default, views use a 250 priority for their content hugging, and a 750 priority for their compression resistance. Therefore, it’s easier to stretch a view than it is to shrink it.
4.
Fortunately, there are a few methods you can call to help identify ambiguous layouts. All of these methods should be used only for debugging. Set a breakpoint somewhere where you can access the view hierarchy, and then call one of the following methods from the console:
[hasAmbiguousLayout]
. Available for both iOS and OS X. Call this method on a misplaced view. It returns YES
if the view’s frame is ambiguous. Otherwise, it returns NO
[exerciseAmbiguityInLayout]
. Available for both iOS and OS X. Call this method on a view with ambiguous layout. This will toggle the system between the possible valid solutions.
[constraintsAffectingLayoutForAxis:]
. Available for iOS. Call this method on a view. It returns an array of all the constraints affecting that view along the specified axis.
[constraintsAffectingLayoutForOrientation:]
. Available for OS X. Call this method on a view. It returns an array of all the constraints affecting that view along the specified orientation.
[_autolayoutTrace]
. Available as a private method in iOS. Call this method on a view. It returns a string with diagnostic information about the entire view hierarchy containing that view. Ambiguous views are labeled, and so are views that have [translatesAutoresizingMaskIntoConstraints]
set to YES.
You may need to use Objective-C syntax when running these commands in the console. For example, after the breakpoint halts execution, type call [self.myView exerciseAmbiguityInLayout]
into the console window to call the exerciseAmbiguityInLayout
method on the myView
object. Similarly, type po [self.myView autolayoutTrace]
to print out diagnostic information about the view hierarchy containing myView
.
一个标识出有歧义布局更直观的方法就是使用exerciseAmbiguityInLayout。这将会在有效值之间随机改变视图的frame。然而,每次调用这个方法只会改变frame一次。所以当你启动程序的时候,你根本不会看到改变。创建一个遍历所有视图层级的辅助方法是一个不错的主意,并且让所有的视图都有一个歧义的布局
@implementation UIView (AutoLayoutDebugging)
- (void)exerciseAmiguityInLayoutRepeatedly:(BOOL)recursive {
#ifdef DEBUG
if (self.hasAmbiguousLayout) {
[NSTimer scheduledTimerWithTimeInterval:.5
target:self
selector:@selector(exerciseAmbiguityInLayout)
userInfo:nil
repeats:YES];
}
if (recursive) {
for (UIView *subview in self.subviews) {
[subview exerciseAmbiguityInLayoutRepeatedly:YES];
}
}
#endif
} @end