UIView 中自定布局的 api
2016-08-08 本文已影响505人
Laughingg
// Allows you to perform layout before the drawing cycle happens. -layoutIfNeeded forces layout early
// 允许你在绘制循环之前完成布局, layoutIfNeeded 会提前点发生。
/*
使 view 的当前约束作废,在下一更新循环(view 的绘制)进行约束更新。
当你想要调整view 的subview 的约束的时候。在 app 的主线程中调用这个方法。这个方法是 请求和实现的标签,这个方法影响不会的实现不会立即调用,而是在下一次更新循环中执行。
*/
- (void)setNeedsLayout;
/*
立即实现自动布局
只用这个方法在绘制之前实现自动布局,这个方法会将布局信息发送到 root view ,从 root view 开始布局。
*/
- (void)layoutIfNeeded;
/*
override point. called by layoutIfNeeded automatically.
重载这个方法,通过 layoutIfNeeded 来自动调用这个方法。
As of iOS 6.0, when constraints-based layout is used the base implementation applies the constraints-based layout, otherwise it does nothing.
只有实现了这个方法,自动布局会根据这实现提供的布局进行布局。否则就什么也不会发生。
在 iOS5.1 之前这个方法什么也没做,否则,这个默认实现会使用任何已经设置的约束去确定 subview 的尺寸和位置。
子类能够重载这个方法去完成子类的子视图的精确布局。
只有在子视图的 autoresizing 和 constraint-based 提供的布局行为不是你想要的时候你才重载这个方法。
你能够使用这个方法的实现,直接设置你 subview 的frame。
你不能直接调用这个方法,如果你想要约束进行更新。
你应该调用 `setNeedsLayout` 方法,在下一次视图绘制之前更新约束。
如果你想view 的layout 的约束更新立即实现。你也可以调用 `layoutIfNeeded` 方法。
*/
- (void)layoutSubviews;
/*
-layoutMargins returns a set of insets from the edge of the view's bounds that denote a default spacing for laying out content.
If preservesSuperviewLayoutMargins is YES, margins cascade down the view tree, adjusting for geometry offsets, so that setting the left value of layoutMargins on a superview will affect the left value of layoutMargins for subviews positioned close to the left edge of their superview's bounds
If your view subclass uses layoutMargins in its layout or drawing, override -layoutMarginsDidChange in order to refresh your view if the margins change.
*/
// 布局间隙
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
// 是否保留父视图的布局间隙
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0); // default is NO - set to enable pass-through or cascading behavior of margins from this view’s parent to its children
// 布局间隙指导
- (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);
/* The edges of this guide are constrained to equal the edges of the view inset by the layoutMargins
*/
@property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0);
/// This content guide provides a layout area that you can use to place text and related content whose width should generally be constrained to a size that is easy for the user to read. This guide provides a centered region that you can place content within to get this behavior for this view.
@property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide NS_AVAILABLE_IOS(9_0);
//
// UIView Constraint-based Layout Support
//
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
// 水平轴
UILayoutConstraintAxisHorizontal = 0,
// 竖直轴
UILayoutConstraintAxisVertical = 1
};
// Installing Constraints ( 约束安装 )
/* A constraint is typically installed on the closest common ancestor of the views involved in the constraint.
一个约束通常是安装在最近的共同祖先的视图。
It is required that a constraint be installed on _a_ common ancestor of every view involved.
The numbers in a constraint are interpreted in the coordinate system of the view it is installed on.
A view is considered to be an ancestor of itself.
*/
@interface UIView (UIConstraintBasedLayoutInstallingConstraints)
@property(nonatomic,readonly) NSArray<__kindof NSLayoutConstraint *> *constraints NS_AVAILABLE_IOS(6_0);
// 添加一个约束
// This method will be deprecated in a future release and should be avoided. Instead, set NSLayoutConstraint's active property to YES.
// 这个方法会在将来的发布版本中被弃用,请避免使用。
// 替代, 设置 NSLayoutConstraint's 的 active 的属性为 yes.
- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
// 添加多个约束
// This method will be deprecated in a future release and should be avoided. Instead use +[NSLayoutConstraint activateConstraints:].
// 这个方法将会在将来的发布版本中弃用,请避免使用。
// 替代, +[NSLayoutConstraint activateConstraints:].
- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
// 移除一个约束
// This method will be deprecated in a future release and should be avoided. Instead set NSLayoutConstraint's active property to NO.
// 这个方法会在将来的发布版本中弃用,请避免使用。
// 替代,设置 NSLayoutConstraint's 的 active 的属性为 no.
- (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
// 移除多个约束
// This method will be deprecated in a future release and should be avoided. Instead use +[NSLayoutConstraint deactivateConstraints:].
// 这个方法会在将来的发布版本中弃用,请避免使用。
// 替代, +[NSLayoutConstraint deactivateConstraints:].
- (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
@end
// Core Layout Methods (核心布局方法)
/* To render a window, the following passes will occur, if necessary.
如果必要,呈现一个 window 后,下面的事项将会发生。
// 更新约束
update constraints
// 布局
layout
// 显示
display
Please see the conceptual documentation for a discussion of these methods.
请参见概念性文档的讨论这些方法。
*/
@interface UIView (UIConstraintBasedLayoutCoreMethods)
// Updates the constraints from the bottom up for the view hierarchy rooted at the receiver. UIWindow's implementation creates a layout engine if necessary first.
// 从视图层级底部更新到上部分,UIWindow 在必要的情况下回创建约束引擎
/*
子类不会重载这个方法。
每当一个 view 的新的布局被触发的时候,系统将会调用这个方法来确保view 和subview的根据当前视图的层级和约束信息来更新任何约束。这个方法会被系统自动调用,也可能被手动触发
,如果你需要检查最新的约束。
*/
- (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0);
// Override this to adjust your special constraints during a constraints update pass
// 重载这个约束去调整你指定的约束,在约束的调整过程中。
/*
调用 [super updateConstraints] 作为实现的最后一步。
*/
- (void)updateConstraints NS_AVAILABLE_IOS(6_0);
// 一个布尔值来决定是否需要更新视图的约束。
- (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0);
// 控件视图的约束是否需要更新。
/*
当自定义的视图的属性发生改变的时候,这个改变将会影响约束。你能够调用这个方法。去表明在将来的某个时间点约束需要更新。 系统之后将会调用 updateConstraints 作为正常布局的一部分。
*/
- (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0);
@end
// Compatibility and Adoption
@interface UIView (UIConstraintBasedCompatibility)
/* By default, the autoresizing mask on a view gives rise to constraints that fully determine
the view's position. This allows the auto layout system to track the frames of views whose
layout is controlled manually (through -setFrame:, for example).
When you elect to position the view using auto layout by adding your own constraints,
you must set this property to NO. IB will do this for you.
*/
@property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES
/* constraint-based layout engages lazily when someone tries to use it (e.g., adds a constraint to a view). If you do all of your constraint set up in -updateConstraints, you might never even receive updateConstraints if no one makes a constraint. To fix this chicken and egg problem, override this method to return YES if your view needs the window to use constraint-based layout.
*/
+ (BOOL)requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
@end
// Separation of Concerns
@interface UIView (UIConstraintBasedLayoutLayering)
/* Constraints do not actually relate the frames of the views, rather they relate the "alignment rects" of views. This is the same as the frame unless overridden by a subclass of UIView. Alignment rects are the same as the "layout rects" shown in Interface Builder 3. Typically the alignment rect of a view is what the end user would think of as the bounding rect around a control, omitting ornamentation like shadows and engraving lines. The edges of the alignment rect are what is interesting to align, not the shadows and such.
*/
/* These two methods should be inverses of each other. UIKit will call both as part of layout computation.
They may be overridden to provide arbitrary transforms between frame and alignment rect, though the two methods must be inverses of each other.
However, the default implementation uses -alignmentRectInsets, so just override that if it's applicable. It's easier to get right.
A view that displayed an image with some ornament would typically override these, because the ornamental part of an image would scale up with the size of the frame.
Set the NSUserDefault UIViewShowAlignmentRects to YES to see alignment rects drawn.
*/
- (CGRect)alignmentRectForFrame:(CGRect)frame NS_AVAILABLE_IOS(6_0);
- (CGRect)frameForAlignmentRect:(CGRect)alignmentRect NS_AVAILABLE_IOS(6_0);
/* override this if the alignment rect is obtained from the frame by insetting each edge by a fixed amount. This is only called by alignmentRectForFrame: and frameForAlignmentRect:.
*/
- (UIEdgeInsets)alignmentRectInsets NS_AVAILABLE_IOS(6_0);
- (UIView *)viewForBaselineLayout NS_DEPRECATED_IOS(6_0, 9_0, "Override -viewForFirstBaselineLayout or -viewForLastBaselineLayout as appropriate, instead") __TVOS_PROHIBITED;
/* -viewForFirstBaselineLayout is called by the constraints system when interpreting
the firstBaseline attribute for a view.
For complex custom UIView subclasses, override this method to return the text-based
(i.e., UILabel or non-scrollable UITextView) descendant of the receiver whose first baseline
is appropriate for alignment.
UIView's implementation returns [self viewForLastBaselineLayout], so if the same
descendant is appropriate for both first- and last-baseline layout you may override
just -viewForLastBaselineLayout.
*/
@property(readonly,strong) UIView *viewForFirstBaselineLayout NS_AVAILABLE_IOS(9_0);
/* -viewForLastBaselineLayout is called by the constraints system when interpreting
the lastBaseline attribute for a view.
For complex custom UIView subclasses, override this method to return the text-based
(i.e., UILabel or non-scrollable UITextView) descendant of the receiver whose last baseline
is appropriate for alignment.
UIView's implementation returns self.
*/
@property(readonly,strong) UIView *viewForLastBaselineLayout NS_AVAILABLE_IOS(9_0);
/* Override this method to tell the layout system that there is something it doesn't natively understand in this view, and this is how large it intrinsically is. A typical example would be a single line text field. The layout system does not understand text - it must just be told that there's something in the view, and that that something will take a certain amount of space if not clipped.
In response, UIKit will set up constraints that specify (1) that the opaque content should not be compressed or clipped, (2) that the view prefers to hug tightly to its content.
A user of a view may need to specify the priority of these constraints. For example, by default, a push button
-strongly wants to hug its content in the vertical direction (buttons really ought to be their natural height)
-weakly hugs its content horizontally (extra side padding between the title and the edge of the bezel is acceptable)
-strongly resists compressing or clipping content in both directions.
However, you might have a case where you'd prefer to show all the available buttons with truncated text rather than losing some of the buttons. The truncation might only happen in portrait orientation but not in landscape, for example. In that case you'd want to setContentCompressionResistancePriority:forAxis: to (say) UILayoutPriorityDefaultLow for the horizontal axis.
The default 'strong' and 'weak' priorities referred to above are UILayoutPriorityDefaultHigh and UILayoutPriorityDefaultLow.
Note that not all views have an intrinsicContentSize. UIView's default implementation is to return (UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric). The _intrinsic_ content size is concerned only with data that is in the view itself, not in other views. Remember that you can also set constant width or height constraints on any view, and you don't need to override instrinsicContentSize if these dimensions won't be changing with changing view content.
*/
UIKIT_EXTERN const CGFloat UIViewNoIntrinsicMetric NS_AVAILABLE_IOS(6_0); // -1
- (CGSize)intrinsicContentSize NS_AVAILABLE_IOS(6_0);
- (void)invalidateIntrinsicContentSize NS_AVAILABLE_IOS(6_0); // call this when something changes that affects the intrinsicContentSize. Otherwise UIKit won't notice that it changed.
- (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
- (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
@end
// Size To Fit (尺寸适应)
// 尺寸适应的压缩尺寸
UIKIT_EXTERN const CGSize UILayoutFittingCompressedSize NS_AVAILABLE_IOS(6_0);
// 尺寸适应的扩充尺寸
UIKIT_EXTERN const CGSize UILayoutFittingExpandedSize NS_AVAILABLE_IOS(6_0);
@interface UIView (UIConstraintBasedLayoutFittingSize)
/* The size fitting most closely to targetSize in which the receiver's subtree can be laid out while optimally satisfying the constraints. If you want the smallest possible size, pass UILayoutFittingCompressedSize; for the largest possible size, pass UILayoutFittingExpandedSize.
Also see the comment for UILayoutPriorityFittingSizeLevel.
*/
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0);
// Equivalent to sending -systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: with UILayoutPriorityFittingSizeLevel for both priorities.
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority NS_AVAILABLE_IOS(8_0);
@end
@interface UIView (UILayoutGuideSupport)
/* UILayoutGuide objects owned by the receiver.
*/
@property(nonatomic,readonly,copy) NSArray<__kindof UILayoutGuide *> *layoutGuides NS_AVAILABLE_IOS(9_0);
/* Adds layoutGuide to the receiver, passing the receiver in -setOwningView: to layoutGuide.
*/
- (void)addLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
/* Removes layoutGuide from the receiver, passing nil in -setOwningView: to layoutGuide.
*/
- (void)removeLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
@end
@class NSLayoutXAxisAnchor,NSLayoutYAxisAnchor,NSLayoutDimension;
@interface UIView (UIViewLayoutConstraintCreation)
/* Constraint creation conveniences. See NSLayoutAnchor.h for details.
*/
@property(readonly, strong) NSLayoutXAxisAnchor *leadingAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutXAxisAnchor *trailingAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutXAxisAnchor *leftAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutXAxisAnchor *rightAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *topAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *bottomAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutDimension *widthAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutDimension *heightAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutXAxisAnchor *centerXAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *centerYAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *firstBaselineAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *lastBaselineAnchor NS_AVAILABLE_IOS(9_0);
@end
// Debugging
/* Everything in this section should be used in debugging only, never in shipping code. These methods may not exist in the future - no promises.
*/
@interface UIView (UIConstraintBasedLayoutDebugging)
/* This returns a list of all the constraints that are affecting the current location of the receiver. The constraints do not necessarily involve the receiver, they may affect the frame indirectly.
Pass UILayoutConstraintAxisHorizontal for the constraints affecting [self center].x and CGRectGetWidth([self bounds]), and UILayoutConstraintAxisVertical for the constraints affecting[self center].y and CGRectGetHeight([self bounds]).
*/
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
/* If there aren't enough constraints in the system to uniquely determine layout, we say the layout is ambiguous. For example, if the only constraint in the system was x = y + 100, then there are lots of different possible values for x and y. This situation is not automatically detected by UIKit, due to performance considerations and details of the algorithm used for layout.
The symptom of ambiguity is that views sometimes jump from place to place, or possibly are just in the wrong place.
-hasAmbiguousLayout runs a check for whether there is another center and bounds the receiver could have that could also satisfy the constraints.
-exerciseAmbiguousLayout does more. It randomly changes the view layout to a different valid layout. Making the UI jump back and forth can be helpful for figuring out where you're missing a constraint.
*/
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);
- (void)exerciseAmbiguityInLayout NS_AVAILABLE_IOS(6_0);
@end