UIView
//
// UIView.h
// UIKit
//
// Copyright (c) 2005-2015 Apple Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIResponder.h>
#import <UIKit/UIInterface.h>
#import <UIKit/UIKitDefines.h>
#import <UIKit/UIAppearance.h>
#import <UIKit/UIDynamicBehavior.h>
#import <UIKit/NSLayoutConstraint.h>
#import <UIKit/UITraitCollection.h>
#import <UIKit/UIFocus.h>
NS_ASSUME_NONNULL_BEGIN
// UIView 动画曲线
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
// 先慢后快再慢
UIViewAnimationCurveEaseInOut, // slow at beginning and end
// 开始慢
UIViewAnimationCurveEaseIn, // slow at beginning
// 结束慢
UIViewAnimationCurveEaseOut, // slow at end
// 线性变化的
UIViewAnimationCurveLinear
};
// UIView 内容模式
/*
Scale: 缩放
Fill: 填充,填满。
*/
typedef NS_ENUM(NSInteger, UIViewContentMode) {
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit, // contents scaled to fit with fixed aspect. remainder is transparent
UIViewContentModeScaleAspectFill, // contents scaled to fill with fixed aspect. some portion of content may be clipped.
UIViewContentModeRedraw, // redraw on bounds change (calls -setNeedsDisplay)
UIViewContentModeCenter, // contents remain same size. positioned adjusted.
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
};
// 动画过度枚举
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
};
// 自动尺寸设置枚举 Autoresizing
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
// 动画选项
typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
UIViewAnimationOptionLayoutSubviews = 1 << 0,
UIViewAnimationOptionAllowUserInteraction = 1 << 1, // turn on user interaction while animating
UIViewAnimationOptionBeginFromCurrentState = 1 << 2, // start all views from current value, not initial value
UIViewAnimationOptionRepeat = 1 << 3, // repeat animation indefinitely
UIViewAnimationOptionAutoreverse = 1 << 4, // if repeat, run animation back and forth
UIViewAnimationOptionOverrideInheritedDuration = 1 << 5, // ignore nested duration
UIViewAnimationOptionOverrideInheritedCurve = 1 << 6, // ignore nested curve
UIViewAnimationOptionAllowAnimatedContent = 1 << 7, // animate contents (applies to transitions only)
UIViewAnimationOptionShowHideTransitionViews = 1 << 8, // flip to/from hidden state instead of adding/removing
UIViewAnimationOptionOverrideInheritedOptions = 1 << 9, // do not inherit any options or animation type
UIViewAnimationOptionCurveEaseInOut = 0 << 16, // default
UIViewAnimationOptionCurveEaseIn = 1 << 16,
UIViewAnimationOptionCurveEaseOut = 2 << 16,
UIViewAnimationOptionCurveLinear = 3 << 16,
UIViewAnimationOptionTransitionNone = 0 << 20, // default
UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20,
UIViewAnimationOptionTransitionFlipFromRight = 2 << 20,
UIViewAnimationOptionTransitionCurlUp = 3 << 20,
UIViewAnimationOptionTransitionCurlDown = 4 << 20,
UIViewAnimationOptionTransitionCrossDissolve = 5 << 20,
UIViewAnimationOptionTransitionFlipFromTop = 6 << 20,
UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20,
} NS_ENUM_AVAILABLE_IOS(4_0);
// 关键帧动画选项
typedef NS_OPTIONS(NSUInteger, UIViewKeyframeAnimationOptions) {
UIViewKeyframeAnimationOptionLayoutSubviews = UIViewAnimationOptionLayoutSubviews,
UIViewKeyframeAnimationOptionAllowUserInteraction = UIViewAnimationOptionAllowUserInteraction, // turn on user interaction while animating
UIViewKeyframeAnimationOptionBeginFromCurrentState = UIViewAnimationOptionBeginFromCurrentState, // start all views from current value, not initial value
UIViewKeyframeAnimationOptionRepeat = UIViewAnimationOptionRepeat, // repeat animation indefinitely
UIViewKeyframeAnimationOptionAutoreverse = UIViewAnimationOptionAutoreverse, // if repeat, run animation back and forth
UIViewKeyframeAnimationOptionOverrideInheritedDuration = UIViewAnimationOptionOverrideInheritedDuration, // ignore nested duration
UIViewKeyframeAnimationOptionOverrideInheritedOptions = UIViewAnimationOptionOverrideInheritedOptions, // do not inherit any options or animation type
UIViewKeyframeAnimationOptionCalculationModeLinear = 0 << 10, // default
UIViewKeyframeAnimationOptionCalculationModeDiscrete = 1 << 10,
UIViewKeyframeAnimationOptionCalculationModePaced = 2 << 10,
UIViewKeyframeAnimationOptionCalculationModeCubic = 3 << 10,
UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10
} NS_ENUM_AVAILABLE_IOS(7_0);
// 系统动画
typedef NS_ENUM(NSUInteger, UISystemAnimation) {
UISystemAnimationDelete, // removes the views from the hierarchy when complete
} NS_ENUM_AVAILABLE_IOS(7_0);
// 色调调整模式
typedef NS_ENUM(NSInteger, UIViewTintAdjustmentMode) {
UIViewTintAdjustmentModeAutomatic,
UIViewTintAdjustmentModeNormal,
UIViewTintAdjustmentModeDimmed,
} NS_ENUM_AVAILABLE_IOS(7_0);
// 语义内容属性
typedef NS_ENUM(NSInteger, UISemanticContentAttribute) {
UISemanticContentAttributeUnspecified = 0,
UISemanticContentAttributePlayback, // for playback controls such as Play/RW/FF buttons and playhead scrubbers
UISemanticContentAttributeSpatial, // for controls that result in some sort of directional change in the UI, e.g. a segmented control for text alignment or a D-pad in a game
UISemanticContentAttributeForceLeftToRight,
UISemanticContentAttributeForceRightToLeft
} NS_ENUM_AVAILABLE_IOS(9_0);
// 用户界面布局方向
typedef NS_ENUM(NSInteger, UIUserInterfaceLayoutDirection) {
UIUserInterfaceLayoutDirectionLeftToRight,
UIUserInterfaceLayoutDirectionRightToLeft,
} NS_ENUM_AVAILABLE_IOS(5_0);
// 坐标空间协议
@protocol UICoordinateSpace <NSObject>
- (CGPoint)convertPoint:(CGPoint)point toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
- (CGPoint)convertPoint:(CGPoint)point fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
- (CGRect)convertRect:(CGRect)rect toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
- (CGRect)convertRect:(CGRect)rect fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
@property (readonly, nonatomic) CGRect bounds NS_AVAILABLE_IOS(8_0);
@end
UIView 类的声明
// UIView 的类声明
@class UIBezierPath, UIEvent, UIWindow, UIViewController, UIColor, UIGestureRecognizer, UIMotionEffect, CALayer, UILayoutGuide;
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusEnvironment>
+ (Class)layerClass; // default is [CALayer class]. Used when creating the underlying layer for the view.
// 初始化方法 —————— 这下面都是指定初始化方法
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
// 是否允许用户交互
/*
默认是可以进行用户交互的。如果设置为 NO ,用户的事件就会被忽略,并从事件队列中移除。
*/
@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default is YES. if set to NO, user events (touch, keys) are ignored and removed from the event queue.
// 标签
@property(nonatomic) NSInteger tag; // default is 0
// 图层
/*
返回 view 的图层。 永远都会返回一个非空的值。
view 就是 layers 的代理。
*/
@property(nonatomic,readonly,strong) CALayer *layer; // returns view's layer. Will always return a non-nil value. view is layer's delegate
// 这下面都是 iOS 9 新增的
- (BOOL)canBecomeFocused NS_AVAILABLE_IOS(9_0); // NO by default
@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);
@end
视图几何
// 视图几何分类
@interface UIView(UIViewGeometry)
// animatable. do not use frame if view is transformed since it will not correctly reflect the actual location of the view. use bounds + center instead.
/*
如果一个 view 已经 transformed,就不要使用 view 的 frame。因为 frame 不能正确 view 的反应真实的位置。
使用 bounds 和 center 进行替代。
*/
@property(nonatomic) CGRect frame;
// use bounds/center and not frame if non-identity transform. if bounds dimension is odd, center may be have fractional part
// 边界
@property(nonatomic) CGRect bounds; // default bounds is zero origin, frame size. animatable
// 中心点
@property(nonatomic) CGPoint center; // center is center of frame. animatable
// 转换,形变
@property(nonatomic) CGAffineTransform transform; // default is CGAffineTransformIdentity. animatable
// 内容缩放因素
@property(nonatomic) CGFloat contentScaleFactor NS_AVAILABLE_IOS(4_0);
// 是否允许多点触摸 (默认是不支持多点触摸)
@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled __TVOS_PROHIBITED; // default is NO
// 是否是单独的触摸
@property(nonatomic,getter=isExclusiveTouch) BOOL exclusiveTouch __TVOS_PROHIBITED; // default is NO
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; // default returns YES if point is in bounds
// 坐标转换操作
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;
- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;
// 是否自动设置 子 view 的尺寸。 默认是 yes。 如果 self 的 bounds 的 changes 发生改变的时候。就会根据 子 view 的 autoresizingMask 调整尺寸。
@property(nonatomic) BOOL autoresizesSubviews; // default is YES. if set, subviews are adjusted according to their autoresizingMask if self.bounds changes
// 自动设置尺寸 默认是
@property(nonatomic) UIViewAutoresizing autoresizingMask; // simple resize. default is UIViewAutoresizingNone
- (CGSize)sizeThatFits:(CGSize)size; // return 'best' size to fit given size. does not actually resize view. Default is return existing view size
- (void)sizeToFit; // calls sizeThatFits: with current view bounds and changes bounds size.
@end
视图层级
// 视图层级分类
@interface UIView(UIViewHierarchy)
// 获取父视图
@property(nullable, nonatomic,readonly) UIView *superview;
// 获取子视图数组
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews;
// 获取 window
@property(nullable, nonatomic,readonly) UIWindow *window;
// 从俯视图中移除
- (void)removeFromSuperview;
// 插入子视图 在 subviews 数组中的 index位置
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
// 改变两个 subviews 在数组中的位置
- (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;
// 在某个视图放到最后面
- (void)sendSubviewToBack:(UIView *)view;
// 已经添加子视图
- (void)didAddSubview:(UIView *)subview;
// 将要移除子视图
- (void)willRemoveSubview:(UIView *)subview;
// 将要移到父视图
- (void)willMoveToSuperview:(nullable UIView *)newSuperview;
// 移到父视图
- (void)didMoveToSuperview;
// 将要移到 Windows
- (void)willMoveToWindow:(nullable UIWindow *)newWindow;
// 移动到 window
- (void)didMoveToWindow;
// 判断某个视图是个是某个 view 的子视图
- (BOOL)isDescendantOfView:(UIView *)view; // returns YES for self.
// 根据 tag 来获取子视图或者自己
- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag; // recursive search. includes self
// -------------- 自动布局 -----------
// Allows you to perform layout before the drawing cycle happens. -layoutIfNeeded forces layout early
- (void)setNeedsLayout;
- (void)layoutIfNeeded;
// override point. called by layoutIfNeeded automatically.
// As of iOS 6.0, when constraints-based layout is used the base implementation applies the constraints-based layout, otherwise it does nothing.
// 这个方法是用来重载的,通过调用 layoutIfNeeded 来自动调用。
- (void)layoutSubviews;
/*
设置一个标记,异步调用 layoutIfNeeded . 布局不会立即刷新,但是一定会刷新。
作废当前的布局,触发一个布局更新在下一个更新循环里面。
当你要调整视图的子视图的布局的时候你需要在主线程中调用这个方法。
这个方法做了一个请求执行的标记。因为这个方法不会导致直接更新,替代是去等待下一次更新循环。
这个行为总是允许你在每一次更新循环中加强所有约束的更新,通常情况下可以提供更好的性能。
- (void)setNeedsLayout;
调用这个方法会立即刷新布局。
这个方法会在子视图之前调用。
- (void)layoutIfNeeded;
用户不能直接调用这个方法,必须调用 layoutIfNeeded 来自动调用 layoutSubviews 方法。
- (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);
// default is NO - set to enable pass-through or cascading behavior of margins from this view’s parent to its children
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0);
// 布局间隙发生改变
- (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);
@end
视图渲染
// 视图渲染分类
@interface UIView(UIViewRendering)
- (void)drawRect:(CGRect)rect;
- (void)setNeedsDisplay;
- (void)setNeedsDisplayInRect:(CGRect)rect;
// 内容和子视图被切除到自己的 bounds 。默认是 no
@property(nonatomic) BOOL clipsToBounds; // When YES, content and subviews are clipped to the bounds of the view. Default is NO.
// 背景颜色(默认是nil,可以在自定义UIView有用外观代理子类。 )
@property(nullable, nonatomic,copy) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; // default is nil. Can be useful with the appearance proxy on custom UIView subclasses.
// 透明度
@property(nonatomic) CGFloat alpha; // animatable. default is 1.0
// 是否是不透明
@property(nonatomic,getter=isOpaque) BOOL opaque; // default is YES. opaque views must fill their entire bounds or the results are undefined. the active CGContext in drawRect: will not have been cleared and may have non-zeroed pixels
// 在绘制之前清除上下文
@property(nonatomic) BOOL clearsContextBeforeDrawing; // default is YES. ignored for opaque views. for non-opaque views causes the active CGContext in drawRect: to be pre-filled with transparent pixels
// 是否隐藏
@property(nonatomic,getter=isHidden) BOOL hidden; // default is NO. doesn't check superviews
// 内容模式
@property(nonatomic) UIViewContentMode contentMode; // default is UIViewContentModeScaleToFill
// 内容的延展
@property(nonatomic) CGRect contentStretch NS_DEPRECATED_IOS(3_0,6_0) __TVOS_PROHIBITED; // animatable. default is unit rectangle {{0,0} {1,1}}. Now deprecated: please use -[UIImage resizableImageWithCapInsets:] to achieve the same effect.
// 遮罩视图
@property(nullable, nonatomic,strong) UIView *maskView NS_AVAILABLE_IOS(8_0);
/*
-tintColor always returns a color. The color returned is the first non-default value in the receiver's superview chain (starting with itself).
If no non-default value is found, a system-defined color is returned.
If this view's -tintAdjustmentMode returns Dimmed, then the color that is returned for -tintColor will automatically be dimmed.
If your view subclass uses tintColor in its rendering, override -tintColorDidChange in order to refresh the rendering if the color changes.
*/
// 渲染颜色
@property(null_resettable, nonatomic, strong) UIColor *tintColor NS_AVAILABLE_IOS(7_0);
/*
-tintAdjustmentMode always returns either UIViewTintAdjustmentModeNormal or UIViewTintAdjustmentModeDimmed. The value returned is the first non-default value in the receiver's superview chain (starting with itself).
If no non-default value is found, UIViewTintAdjustmentModeNormal is returned.
When tintAdjustmentMode has a value of UIViewTintAdjustmentModeDimmed for a view, the color it returns from tintColor will be modified to give a dimmed appearance.
When the tintAdjustmentMode of a view changes (either the view's value changing or by one of its superview's values changing), -tintColorDidChange will be called to allow the view to refresh its rendering.
*/
// 色调调整模式
@property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode NS_AVAILABLE_IOS(7_0);
/*
The -tintColorDidChange message is sent to appropriate subviews of a view when its tintColor is changed by client code or to subviews in the view hierarchy of a view whose tintColor is implicitly changed when its superview or tintAdjustmentMode changes.
*/
// 色调颜色已经改变
- (void)tintColorDidChange NS_AVAILABLE_IOS(7_0);
@end
动画分类
// UIView 动画分类
@interface UIView(UIViewAnimation)
// 开启动画
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context; // additional context info passed to will start/did stop selectors. begin/commit can be nested
// 提交动画
+ (void)commitAnimations; // starts up any animations when the top level animation is commited
// no getters. if called outside animation block, these setters have no effect.
// 设置动画代理
+ (void)setAnimationDelegate:(nullable id)delegate; // default = nil
// 设置动画开始调用的方法
+ (void)setAnimationWillStartSelector:(nullable SEL)selector; // default = NULL. -animationWillStart:(NSString *)animationID context:(void *)context
// 设置动画结束开始调用的方法
+ (void)setAnimationDidStopSelector:(nullable SEL)selector; // default = NULL. -animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
// 设置动画持续时间
+ (void)setAnimationDuration:(NSTimeInterval)duration; // default = 0.2
// 设置动画延迟时间
+ (void)setAnimationDelay:(NSTimeInterval)delay; // default = 0.0
// 设置动画开始时间
+ (void)setAnimationStartDate:(NSDate *)startDate; // default = now ([NSDate date])
// 设置动画曲线
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve; // default = UIViewAnimationCurveEaseInOut
// 设置动画重复次数
+ (void)setAnimationRepeatCount:(float)repeatCount; // default = 0.0. May be fractional
// 设置是否自动反转
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses; // default = NO. used if repeat count is non-zero
// 设置动画开始状态
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState; // default = NO. If YES, the current view position is always used for new animations -- allowing animations to "pile up" on each other. Otherwise, the last end state is used for the animation (the default).
// 设置动画过度样式
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; // current limitation - only one per begin/commit block
// 设置动画是否可用
+ (void)setAnimationsEnabled:(BOOL)enabled; // ignore any attribute changes while set.
// 判断现在是否在执行动画
+ (BOOL)areAnimationsEnabled;
// 执行 block 动画
+ (void)performWithoutAnimation:(void (^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0);
// 继承的时间间隔
+ (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
@end
// UIView block 动画
@interface UIView(UIViewAnimationWithBlocks)
// 这个方法是用的最多的
/*
Duration : 动画持续时间
delay : 动画延迟时间
options : 动画选项
animations : 执行的动画块
completion : 动画完成后执行的块
*/
+ (void)animateWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
/*
Duration : 动画持续时间
animations : 执行的动画块
completion : 动画完成后执行的块
*/
+ (void)animateWithDuration:(NSTimeInterval)duration
animations:(void (^)(void))animations
completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0
/*
Duration : 动画持续时间
animations : 执行的动画块
*/
+ (void)animateWithDuration:(NSTimeInterval)duration
animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL
/* Performs `animations` using a timing curve described by the motion of a spring.
动画的执行使用一个时间曲线来描述。(一个运动的弹框)
When `dampingRatio` is 1, the animation will smoothly decelerate to its final model values without oscillating.
当 dampingRatio 是 1。动画会一个平稳的减速到最终的值。没有震荡。
Damping ratios less than 1 will oscillate more and more before coming to a complete stop.
阻尼率,比1 小,将会不停的震荡,直到停止。
You can use the initial spring velocity to specify how fast the object at the end of the simulated spring was moving before it was attached.
It's a unit coordinate system, where 1 is defined as travelling the total animation distance in a second.
So if you're changing an object's position by 200pt in this animation, and you want the animation to behave as if the object was moving at 100pt/s before the animation started, you'd pass 0.5.
You'll typically want to pass 0 for the velocity. */
// 这个方法是iOS7 新加的可以用来创建弹性动画。
/*
duration : 动画的持续时间
delay : 动画的延迟
usingSpringWithDamping : 弹性率的
initialSpringVelocity : 弹性速度
options : 动画选项
animations : 动画
completion : 动画完成的回调
*/
+ (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 NS_AVAILABLE_IOS(7_0);
// 过度动画
+ (void)transitionWithView:(UIView *)view
duration:(NSTimeInterval)duration
options:(UIViewAnimationOptions)options
animations:(void (^ __nullable)(void))animations
completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
+ (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
/* Performs the requested system-provided animation on one or more views. Specify addtional animations in the parallelAnimations block. These additional animations will run alongside the system animation with the same timing and duration that the system animation defines/inherits. Additional animations should not modify properties of the view on which the system animation is being performed. Not all system animations honor all available options.
*/
+ (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)
+ (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);
+ (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
// UIView 手势识别
@interface UIView (UIViewGestureRecognizers)
// 获取所有的手势识别
@property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers NS_AVAILABLE_IOS(3_2);
// 添加手势识别
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);
// 移除手势识别
- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);
// called when the recognizer attempts to transition out of UIGestureRecognizerStatePossible if a touch hit-tested to this view will be cancelled as a result of gesture recognition
// returns YES by default. return NO to cause the gesture recognizer to transition to UIGestureRecognizerStateFailed
// subclasses may override to prevent recognition of particular gestures. for example, UISlider prevents swipes parallel to the slider that start in the thumb
// 手势识别将要开始
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer NS_AVAILABLE_IOS(6_0);
@end
运动 效果分类
// UIView 的 运动 效果分类
@interface UIView (UIViewMotionEffects)
/*! Begins applying `effect` to the receiver. The effect's emitted keyPath/value pairs will be
applied to the view's presentation layer.
Animates the transition to the motion effect's values using the present UIView animation
context. */
- (void)addMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);
/*! 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);
@property (copy, nonatomic) NSArray<__kindof UIMotionEffect *> *motionEffects NS_AVAILABLE_IOS(7_0);
@end
自动布局
//
// UIView Constraint-based Layout Support
// UIView 的布局约束支持
//
// 布局约束 轴 的枚举
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.
- (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:].
- (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.
- (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:].
- (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.
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.
- (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0);
// 更新约束
// Override this to adjust your special constraints during a constraints update pass
- (void)updateConstraints NS_AVAILABLE_IOS(6_0);
// 是否需要更新约束
- (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0);
// 更新约束
- (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0);
@end
// Compatibility and Adoption autoresizing 和 outLayot 的兼容
@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.
*/
// 是否将 Autoresizing Mask 转换为约束 (默认是 yes)
@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.
去修复一个🐔与蛋的问题,重载这个方法,返回 yes。如果你需要这个视图基于 window 的 约束布局。
在不使用 autoresizing 的情况下,这个值必须是yes (默认也是 yes)
是否使用自动布局系统
*/
// 需要基于约束的布局
+ (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.
Equivalent to sending - systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: with UILayoutPriorityFittingSizeLevel for both priorities.
*/
// 返回一个满足约束的视图大小
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0);
// 返回满足约束的视图的大小。
- (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;
// 布局约束的创建 (这个分类只有在iOS9 中才使用 )
@interface UIView (UIViewLayoutConstraintCreation)
/* Constraint creation conveniences. See NSLayoutAnchor.h for details.
*/
// x 轴 前面的锚点
@property(readonly, strong) NSLayoutXAxisAnchor *leadingAnchor NS_AVAILABLE_IOS(9_0);
// x 轴 后面的锚点
@property(readonly, strong) NSLayoutXAxisAnchor *trailingAnchor NS_AVAILABLE_IOS(9_0);
// x 轴 左边的锚点
@property(readonly, strong) NSLayoutXAxisAnchor *leftAnchor NS_AVAILABLE_IOS(9_0);
// x 轴 右边的锚点
@property(readonly, strong) NSLayoutXAxisAnchor *rightAnchor NS_AVAILABLE_IOS(9_0);
// y轴 上面的锚点
@property(readonly, strong) NSLayoutYAxisAnchor *topAnchor NS_AVAILABLE_IOS(9_0);
// y轴 下面的锚点
@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);
// x轴,center 锚点
@property(readonly, strong) NSLayoutXAxisAnchor *centerXAnchor NS_AVAILABLE_IOS(9_0);
// y轴,center 锚点
@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
@interface UIView (UIStateRestoration)
@property (nullable, nonatomic, copy) NSString *restorationIdentifier NS_AVAILABLE_IOS(6_0);
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
- (void) decodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
@end
// UIView 快照操作分类
@interface UIView (UISnapshotting)
/*
* When requesting a snapshot, 'afterUpdates' defines whether the snapshot is representative of what's currently on screen or if you wish to include any recent changes before taking the snapshot.
If called during layout from a committing transaction, snapshots occurring after the screen updates will include all changes made, regardless of when the snapshot is taken and the changes are made. For example:
- (void)layoutSubviews {
UIView *snapshot = [self snapshotViewAfterScreenUpdates:YES];
self.alpha = 0.0;
}
The snapshot will appear to be empty since the change in alpha will be captured by the snapshot. If you need to animate the view during layout, animate the snapshot instead.
* Creating snapshots from existing snapshots (as a method to duplicate, crop or create a resizable variant) is supported. In cases where many snapshots are needed, creating a snapshot from a common superview and making subsequent snapshots from it can be more performant. Please keep in mind that if 'afterUpdates' is YES, the original snapshot is committed and any changes made to it, not the view originally snapshotted, will be included.
*/
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
- (UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0); // Resizable snapshots will default to stretching the center
// Use this method to render a snapshot of the view hierarchy into the current context. Returns NO if the snapshot is missing image data, YES if the snapshot is complete. Calling this method from layoutSubviews while the current transaction is committing will capture what is currently displayed regardless if afterUpdates is YES.
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
@end
NS_ASSUME_NONNULL_END