UIView是iOS开发中最熟悉的控件,不是因为它用得多,而是很多UI控件都是继承它的,了解它的分类方法是很有必要的。
UIView其实是由多个分类构成,主要有如下几个分类:
UIView :基本属性,tag、layer、可否交互等设置
以下是分类UIView ()
UIViewGeometry : 几何特征 位置 【frame 、bound 、center 、等】
UIViewHierarchy : 层级
UiViewRendering : 渲染/打底
UIViewAnimation : 动画
UIViewAnimationWithBlocks : 动画回掉
UIViewKeyframeAnimation : 关键帧动画
UIViewGestureRecongizers : 手势识别
UIViewMotionEffects : 运动影响
与约束有关的
UIConstraintBasedInstallingConstraints
UIConstraintBasedLayoutCoreMethod
UIConstraintBasedCompatibility
UIConstraintBasedLayoutLayering
UIConstraintBasedLayoutFittingSize
UIConstraintBasedLayoutDebugging
UILayoutGuideSuport :
@interface UIView : UIResponder
+ (Class)layerClass; // UIView有个layer属性,可以返回它的主CALayer实例,UIView有一个layerClass方法,返回主layer所使用的类,UIView的子类可以通过重载这个方法来让UIView使用不同的CALayer来显示
- (instancetype)initWithFrame:(CGRect)frame; // 便利初始化方法:根据frame创建视图
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // 是否可以与用户交互
@property(nonatomic) NSInteger tag; // 当前视图的标签,默认是0
@property(nonatomic,readonly,strong) CALayer *layer; // 用来视图渲染的核心动画层
- (BOOL)canBecomeFocused NS_AVAILABLE_IOS(9_0); // //是否能被设置为高亮,默认呢是N
@property (readonly, nonatomic, getter=isFocused) BOOL focused NS_AVAILABLE_IOS(9_0);
+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)attribute NS_AVAILABLE_IOS(9_0);
@property (nonatomic) UISemanticContentAttribute semanticContentAttribute NS_AVAILABLE_IOS(9_0);
基本定义主要包含初始化、tag、交互性、layer层
从定义可以看出,UIView是基于UIResponder的,所有具有响应功能,可以处理点击事件(Touch Events)、运动事件(motion Events)、远程控制事件(Remote Control Events )只有程序在强制退出和来电时才会调用取消点击事件,所有继承UIResponder的子类都可以直接响应事件,称为响应者。
顺便提一下iOS的事件响应链,
当有点击事件发生时,系统会为其创建一个含点击信息的UITouch和UIEVent的实例,然后找到当前程序,逐级寻找能响应这个时间的对象,直到没有响应者为止,一般响应链寻找顺序如下图:
二、UIViewGeometry :几何位置
该分类主要决定该View的几何与位置
@interface UIView(UIViewGeometry)
@property(nonatomic) CGRect frame; // 当前视图的边界,包括大小和原点,这里是在父视图的坐标系下 (当处于动画中,或者不是最后显示的时候,建议使用bounds和center来确定位置)
@property(nonatomic) CGRect bounds; // 当前视图的边界,包括大小和原点,这里是在自己的坐标系下
@property(nonatomic) CGPoint center; // 当前视图的中心,并制定是在父视图的坐标系下
@property(nonatomic) CGAffineTransform transform; // 形变属性(平移/缩放/旋转)
/////////////////////////transform实例////////////////////////////////////////////////////////
UIView 的旋转和缩放
view.transform = CGAffineTransformMakeRotation(90 *M_PI / 180.0);
//顺时针旋转 90度
view.transform = CGAffineTransformMakeRotation(180 *M_PI / 180.0);
//顺时针 旋转180度
view.transform = CGAffineTransformMakeRotation(270 *M_PI / 180.0);
//顺时针旋转270度
CGAffineTransform transform = view.transform;
transform = CGAffineTransformScale(transform, 2,0.5);//前面的2表示横向放大2倍,后边的0.5表示纵向缩小一半
view.transform = transform;
//////////////////////////transform实例//////////////////////////////////////////////////////////
该分类主要用于管理View中子视图关系的。
@interface UIView(UIViewHierarchy)
@property(nullable, nonatomic,readonly) UIView *superview; // 获取父视图,只读属性
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews; // 当前视图的所有子视图,只读属性
@property(nullable, nonatomic,readonly) UIWindow *window; // 当前视图上的UIWindow对象,只读属性
- (void)removeFromSuperview; // 从父视图移除
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index; // 在索引位置插入一个视图
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2; // 用索引值交换两个视图
- (void)addSubview:(UIView *)view; // 向当前视图上添加子视图
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview; // 在某个视图下插入一个视图
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview; // 在某个视图上插入一个视图
- (void)bringSubviewToFront:(UIView *)view; // 把这个View放到最前面
- (void)sendSubviewToBack:(UIView *)view; // 把这个View放到最后面
- (void)didAddSubview:(UIView *)subview; // 告诉视图添加子视图
- (void)willRemoveSubview:(UIView *)subview; // 即将移除子视图
- (void)willMoveToSuperview:(nullable UIView *)newSuperview; // 即将从父视图移除
- (void)didMoveToSuperview; // 已经移除,父视图改变
- (void)willMoveToWindow:(nullable UIWindow *)newWindow; // 窗口对象即将改变
- (void)didMoveToWindow; // 已经语出窗体对象
#pragma mark - 系统自动调用
- (BOOL)isDescendantOfView:(UIView *)view; // 判定一个视图是否在其父视图的视图层中
- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag; // 返回指定tag的View
#pragma mark - 布局
- (void)setNeedsLayout; // 标记视图需要重新布局,调用下面的方法后会调用layoutSubviews
- (void)layoutIfNeeded; // 当调用了setNeedsLayout并不会马上调用layoutSubViews,这时会调用该方法,可以强制发生重新布
#pragma mark - 系统自动调用(留给子类去实现)
/**
* 控件的frame,约束发生改变的时候就会调用,一般在这里重写布局子控件的位置和尺寸
* 重写了这个方法后一定要调用[super layoutSubviews]
*/
- (void)layoutSubviews; // 对子视图布局
/*
layoutSubviews在以下情况下会被调用:
1、init初始化不会触发layoutSubviews , 但 initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发.
2、addSubview会触发layoutSubviews.
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化.
4、滚动一个UIScrollView会触发layoutSubviews.
5、旋转Screen会触发父UIView上的layoutSubviews事件.
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件.
[1]、layoutSubviews对subviews重新布局
[2]、layoutSubviews方法调用先于drawRect
[3]、setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews
[4]、layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout
[5]、layoutIfNeeded遍历的不是superview链,应该是subviews链
*/
@property (nonatomic) UIEdgeInsets layoutMargins; // 布局视图,距离父视图的上左下右的距离
@property (nonatomic) BOOL preservesSuperviewLayoutMargins; // 这个属性默认是NO,如果把它设为YES,layoutMargins会根据屏幕中相关View的布局而改变
- (void)layoutMarginsDidChange; // 在我们改变View的layoutMargins这个属性时,会触发这个方法。我们在自己的View里面可以重写这个方法来捕获layoutMargins的变化。在大多数情况下,我们可以在这个方法里触发drawing和layout的Update
@property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0);
@property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide NS_AVAILABLE_IOS(9_0);
@end
该分类主要用于UIVeiw的渲染和重绘,颜色边框、透明度
@interface UIView(UIViewRendering)
/**
* drawRect是对receiver的重绘
* setNeedDisplay在receiver标上一个需要被重新绘图的标记,在下一个draw周期自动重绘,iphone device的刷新频率是60hz,也就是1/60秒后重绘
*/
- (void)drawRect:(CGRect)rect; // 渲染 重写此方法 执行重绘
- (void)setNeedsDisplay; // 需要重新渲染 标记为需要重绘 异步步调用drawRect
- (void)setNeedsDisplayInRect:(CGRect)rect; // 需要重新渲染某一块区域
@property(nonatomic) BOOL clipsToBounds; // 决定了子视图的显示范围。具体来说,当取值为YES时,裁剪超出父视图范围的子视图范围,默认值为NO
@property(nullable, nonatomic,copy) UIColor *backgroundColor; // 设置背景颜色 ,默认为nil
@property(nonatomic) CGFloat alpha; // 透明度,0.0-1.0的数值,0为全透明,1为不透明
@property(nonatomic,getter=isOpaque) BOOL opaque; // 是否透明,默认为YES
/*
决定该消息接收者(UIView instance)是否让其视图不透明,用处在于给绘图系统提供一个性能优化开关。
myView.opaque = NO;
该值为YES, 那么绘图在绘制该视图的时候把整个视图当作不透明对待。优化绘图过程并提升系统性能;为了性能方面的考量,默认被置为YES。
该值为NO,,不去做优化操作。
一个不透明视图需要整个边界里面的内容都是不透明。基于这个原因,opaque设置为YES,要求对应的alpha必须为1.0。如果一个UIView实例opaque被设置为YES, 而同时它又没有完全填充它的边界(bounds),或者它包含了整个或部分的透明的内容视图,那么将会导致未知的结果。
因此,如果视图部分或全部支持透明,那么你必须把opaque这个值设置为NO.
*/
@property(nonatomic) BOOL clearsContextBeforeDrawing; // 决定在子视图重画之前是否先清理视图以前的内容
@property(nonatomic,getter=isHidden) BOOL hidden; // 是否隐藏,默认为NO
@property(nonatomic) UIViewContentMode contentMode; // 决定当视图边界变时呈现视图内容的方式
/*
UIViewContentMode枚举值:
UIViewContentModeScaleToFill // 填充
UIViewContentModeScaleAspectFit // 缩放填充
UIViewContentModeRedraw // 重绘边界
UIViewContentModeCenter // 保持相同的大小,居中
UIViewContentModeTop // 保持相同的大小,居上
UIViewContentModeBottom, // 保持相同的大小,居下
UIViewContentModeLeft, // 保持相同的大小,居左
UIViewContentModeRight, // 保持相同的大小,居右
UIViewContentModeTopLeft, // 保持相同的大小,居左上
UIViewContentModeTopRight, // 保持相同的大小,居右上
UIViewContentModeBottomLeft, // 保持相同的大小,居左下
UIViewContentModeBottomRight, // 保持相同的大小,居右下
*/
@property(nonatomic) CGRect contentStretch; // 用于制定哪部分是可拉伸的,取值在0.0~1.0之间
/*
[imageView setContentStretch:CGRectMake(150.0/300.0, 100.0/200.0, 10.0/300.0, 10.0/200.0)];
image.png的大小是 200 x 150 ;
mageView的frame是(0,0,300,200);
150.0/300.0表示x轴上,前150个像素不进行拉伸。
100.0/200.0表示y轴上,前100个像素不进行拉伸。
10.0/300.0表示x轴上150后的10个像素(151-160)进行拉伸,直到image.png铺满imageView。
10.0/200.0表示y轴上100后的10个像素(101-110)进行拉伸,直到image.png铺满imageView。
*/
@property(nullable, nonatomic,strong) UIView *maskView; // 蒙层视图,一个神奇的东西,与动画有关,后期好好学习。
@property(null_resettable, nonatomic, strong) UIColor *tintColor; // 视图控件的颜色
@property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode; // 视图的色彩模式
/*
枚举值:
UIViewTintAdjustmentModeAutomatic, //自动的
UIViewTintAdjustmentModeNormal, //正常的
UIViewTintAdjustmentModeDimmed, //暗淡的
*/
- (void)tintColorDidChange; // 视图颜色属性发生变化时,由系统调用
@end
该分类主要设置一些动画的方法,对UIView简单动画设置。
@interface UIView(UIViewAnimation)
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable voidvoid *)context; // 用来表示动画的开始
+ (void)commitAnimations; // 标记动画结束,执行动画(与beginAnimations方法成对使用)
+ (void)setAnimationDelegate:(nullable id)delegate; // 设置动画代理对象,当动画开始或者结束时会发消息给代理对象
+ (void)setAnimationWillStartSelector:(nullable SEL)selector; // 当动画即将开始时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector
+ (void)setAnimationDidStopSelector:(nullable SEL)selector; // 当动画结束时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector
+ (void)setAnimationDuration:(NSTimeInterval)duration; // 动画的持续时间,秒为单位
+ (void)setAnimationDelay:(NSTimeInterval)delay; // 动画延迟delay秒后再开始
+ (void)setAnimationStartDate:(NSDate *)startDate; // 动画开始的时间,默认为now
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve; // 动画的节奏控制 default = UIViewAnimationCurveEaseInOut
+ (void)setAnimationRepeatCount:(float)repeatCount; // 动画的重复次数
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses; // 如果设置为YES,代表动画每次重复执行的效果会跟上一次相反
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState; // 设置动画开始时的状态
/*
如果是YES,那么在开始和结束图片视图渲染一次并在动画中创建帧;否则,视图将会在每一帧都渲染。例如缓存,你不需要在视图转变中不停的更新,你只需要等到转换完成再去更新视图。
1、开始一个动画块。
2、在容器视图中设置转换。
3、在容器视图中移除子视图。
4、在容器视图中添加子视图。
5、结束动画块。
*/
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; // 设置视图View的过渡效果,transition指定过渡类型,cache设置YES代表使用视图缓存,性能较好
+ (void)setAnimationsEnabled:(BOOL)enabled; // 设置动画是否可用
+ (BOOL)areAnimationsEnabled; // 返回动画效果是否开启
+ (void)performWithoutAnimation:(void (^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0); // 先检查动画当前是否启用,然后禁止动画,执行block内方法,最后重新启用动画。它并不会阻塞局域CoreAnimation的动画
+ (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
@end
动画设置的回掉,可以设置具体怎么实现动画。
@interface UIView(UIViewAnimationWithBlocks)
// 下方三个是属性动画
/**
* 动画效果处理块
*
* @param duration 动画时间
* @param delay 延迟时间
* @param options 动画参数
* @param animations 动画效果块,动画效果在这里面设置
* @param completion 完成效果块
*/
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion; // 一般的动画
// 没有延迟时间 没有动画参数 options默认为0
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion; // delay = 0.0, options = 0
// 动画效果处理块 delay= = 0.0,options = 0,completion = NULL
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL
// Spring(弹簧)Animation的API比一般动画多了两个参数 usingSpringWithDamping(范围为0.0f~1.0f),数值越小弹簧的震动的效果越明显 initialSpringVelocity表示初始速度,数值越大一开始移动越快
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion; // 弹性动画
// 过渡动画效果块
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion; // 转场动画
/////////////////////////动画实例/////////////////////////////
/*
[UIView transitionWithView:_redView
duration:2.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^{
[_blackView removeFromSuperview];
[_redView addSubview:_blackView];
} completion:^(BOOL finished) {
_redView.backgroundColor = [UIColor brownColor];
}];
*/
// 视图之间切换的过渡动画效果块
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview
// 在一组视图上执行指定的系统动画,并可以并行自定义动画。其中parallelAnimations就是与系统动画并行的自定义动画
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
@end
该类是苹果公司为了解决动画部分的代码叠层和代码量过多问题。
@interface UIView (UIViewKeyframeAnimations)
/////////////////////////////关键帧动画实例//////////////////////////////////////
[UIView animateKeyframesWithDuration:2.0delay:0options:UIViewKeyframeAnimationOptionRepeatanimations:^{
_blackView.frame = CGRectMake(30, 30, 50, 50);
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0 animations:^{
_redView.frame = CGRectMake(50, 50, 50, 50);
}];
} completion:^(BOOL finished) {
_redView.frame= CGRectMake(50, 50, 100, 100);;
_blackView.frame = CGRectMake(30, 30, 80, 80);
}];
///////////////////////////关键帧实例//////////////////////////////////////////////////
// 为当前视图创建一个可以用于设置基本关键帧动画的block对象
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
/**
* 指定一个关键帧的单个帧的时间和动画 iOS7后可用
*
* @param frameStartTime 一个倍数从0~1,假设一个动画持续的时间是2秒,设置frameStartTime为0.5 那么后面设置的动画将会在整体动画执行1秒后开始
* @param frameDuration 动画持续时间
* @param animations 动画效果块
*/
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0); // start time and duration are values between 0.0 and 1.0 specifying time and duration relative to the overall time of the keyframe animation
@end
管理手势
@interface UIView (UIViewGestureRecognizers)
@property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers; // 当前视图手势集合
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer; // 添加手势
- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer; // 移除手势
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer; // 通过返回值决定是否识别此手势
@end
@interface UIView (UIViewMotionEffects)
/*
当你打开装有iOS7以上的iPhone主屏,默认的背景是一幅蓝色的星空图片。当上下左右翻转iPhone时,有趣的效果将会出现,星空背景也会沿着各个方向发生位移,这与主屏上的各个App Icon形成了一种独特的视差效果。
//UIMotionEffect
1. UIInterpolatingMotionEffect
UIInterpolatingMotionEffect是UIMotionEffect的子类,虽然扩展也不复杂,提供的方法也很简单,但在很多场景下可以比较直接和方便的满足我们的需求。
它有4个property:
1.keyPath,左右翻转屏幕将要影响到的属性,比如center.x。
2.type(UIInterpolatingMotionEffectType类型),观察者视角,也就是屏幕倾斜的方式,目前区分水平和垂直两种方式。
3.minimumRelativeValue和maximumRelativeValue,keyPath对应的值的变化范围,注意这个是id类型。min对应最小的offset,max对应最大的offset。
UIInterpolatingMotionEffect * xEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
xEffect.minimumRelativeValue = [NSNumber numberWithFloat:-40.0];
xEffect.maximumRelativeValue = [NSNumber numberWithFloat:40.0];
[targetView addMotionEffect:xEffect];
参考自http://www.cocoachina.com/ios/20150121/10967.html
*/
- (void)addMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0); // 添加一个UIMotionEffect
/*! Stops applying `effect` to the receiver. Any affected presentation values will animate to
their post-removal values using the present UIView animation context. */
- (void)removeMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0); // 移除一个UIMotionEffect
@property (copy, nonatomic) NSArray<__kindof UIMotionEffect *> *motionEffects NS_AVAILABLE_IOS(7_0); // 包含的UIMotionEffect
@end
UIConstraintBasedInstallingConstraints
UIConstraintBasedLayoutCoreMethod
UIConstraintBasedCompatibility
UIConstraintBasedLayoutLayering
UIConstraintBasedLayoutFittingSize
UIConstraintBasedLayoutDebugging
UILayoutGuideSuport :
@interface UIView (UIConstraintBasedLayoutInstallingConstraints)
@property(nonatomic,readonly) NSArray<__kindof NSLayoutConstraint *> *constraints NS_AVAILABLE_IOS(6_0); // 视图布局约束
- (void)addConstraint:(NSLayoutConstraint *)constraint; // 添加约束
- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints; // 添加一组约束
- (void)removeConstraint:(NSLayoutConstraint *)constraint; // 移除某个约束
- (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints; // 移除一组约束
@end
// Core Layout Methods
/* To render a window, the following passes will occur, if necessary.
update constraints
layout
display
Please see the conceptual documentation for a discussion of these methods.
*/
@interface UIView (UIConstraintBasedLayoutCoreMethods)
- (void)updateConstraintsIfNeeded; // 更新约束布局及其子布局
- (void)updateConstraints; // 更新约束布局
- (BOOL)needsUpdateConstraints; // 返回约束布局是否需要更新,YES为是
- (void)setNeedsUpdateConstraints; // 设置需要更新的约束布局
@end
// Compatibility and Adoption
@interface UIView (UIConstraintBasedCompatibility)
@property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints; // 返回一个BOOL,判断自动布局是否可以转换约束布局
+ (BOOL)requiresConstraintBasedLayout; // 返回View是否约束布局模式
@end
// Separation of Concerns
@interface UIView (UIConstraintBasedLayoutLayering)
- (CGRect)alignmentRectForFrame:(CGRect)frame; // 返回视图矩形对于指定视图框架
- (CGRect)frameForAlignmentRect:(CGRect)alignmentRect; // 返回框架对于指定视图矩形
- (UIEdgeInsets)alignmentRectInsets; // 返回自定义视图框架
- (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; // 返回view的自然尺寸
- (void)invalidateIntrinsicContentSize; // 使内容尺寸无效化
- (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis; // 返回放大的视图布局的轴线
- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis; // 设置放大的视图布局的轴线
- (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis; // 返回缩小的视图布局的轴线
/*
axis:布局约束
枚举值:
UILayoutConstraintAxisHorizontal //水平
UILayoutConstraintAxisVertical //垂直
返回值:小数
*/
- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis; // 设置缩小的视图布局的轴线
@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)
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize; // 返回最合适的尺寸
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority; // 满足约束视图布局的大小
@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)
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis; // 返回影响视图布局限制的轴线
- (BOOL)hasAmbiguousLayout; // 返回视图布局约束是否影响指定视图,主要用于调试约束布局,结合exerciseAmbiguityInLayout
- (void)exerciseAmbiguityInLayout; // 随机改变不同效值布局视图,主要用于调试基于约束布局的视图
@end
@interface UIView (UIStateRestoration)
@property (nullable, nonatomic, copy) NSString *restorationIdentifier; // 该标识符决定该视图是否支持恢复状态,其实也只是个标识符而已
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder; // 保存视图状态相关信息
- (void) decodeRestorableStateWithCoder:(NSCoder *)coder; // 恢复和保持视图状态相关信息
@end
@interface UIView (UISnapshotting)
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates; // 返回一个基于当前视图的内容快照视图
- (UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets; // 返回一个基于当前视图的特定内容的快照视图,拉伸插图
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates; // 利用View层次结构病将其绘制到当前的上下文中
@end