IOS UIView详解

IOS UIView详解

1.官方类分析

只有主线程才能更新UI。UIKit框架内的组件包括UIView及其子类的所有操作都必须在主线程中进行,否则会出现不可预知的问题。

在这里插入图片描述

UIView的作用

负责内部区域的内容渲染。
负责内部区域的触摸事件。
管理本身的所有子视图。
处理基本的动画。

UIView类头文件:

#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.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
 
/** 动画的曲线枚举 */
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
    UIViewAnimationCurveEaseInOut,  //!< 慢进慢出(默认值).
    UIViewAnimationCurveEaseIn,     //!< 慢进.
    UIViewAnimationCurveEaseOut,    //!< 慢出.
    UIViewAnimationCurveLinear,     //!< 匀速.
};
 
//!< UIView内容填充模式.
typedef NS_ENUM(NSInteger, UIViewContentMode) {
    UIViewContentModeScaleToFill,       //!< 缩放内容到合适比例大小.
    UIViewContentModeScaleAspectFit,    //!< 缩放内容到合适的大小,边界多余部分透明.
    UIViewContentModeScaleAspectFill,   //!< 缩放内容填充到指定大小,边界多余的部分省略.
    UIViewContentModeRedraw,            //!< 重绘视图边界 (需调用 -setNeedsDisplay).
    UIViewContentModeCenter,            //!< 视图保持等比缩放.
    UIViewContentModeTop,               //!< 视图顶部对齐.
    UIViewContentModeBottom,            //!< 视图底部对齐.
    UIViewContentModeLeft,              //!< 视图左侧对齐.
    UIViewContentModeRight,             //!< 视图右侧对齐.
    UIViewContentModeTopLeft,           //!< 视图左上角对齐.
    UIViewContentModeTopRight,          //!< 视图右上角对齐.
    UIViewContentModeBottomLeft,        //!< 视图左下角对齐.
    UIViewContentModeBottomRight,       //!< 视图右下角对齐.
};
 
/** UIView动画过渡效果 */
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
    UIViewAnimationTransitionNone,          //!< 无效果.
    UIViewAnimationTransitionFlipFromLeft,  //!< 沿视图垂直中心轴左到右移动.
    UIViewAnimationTransitionFlipFromRight, //!< 沿视图垂直中心轴右到左移动.
    UIViewAnimationTransitionCurlUp,        //!< 由底部向上卷起.
    UIViewAnimationTransitionCurlDown,      //!< 由顶部向下展开.
};
 
/** 自动调整大小方式 */
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,     //!< 不自动调整.
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,//!< 自动调整与superView左边的距离,保证与superView右边的距离不变.
    UIViewAutoresizingFlexibleWidth        = 1 << 1,//!< 自动调整自己的宽度,保证与superView左边和右边的距离不变.
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,//!< 自动调整与superView的右边距离,保证与superView左边的距离不变.
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,//!< 自动调整与superView顶部的距离,保证与superView底部的距离不变.
    UIViewAutoresizingFlexibleHeight       = 1 << 4,//!< 自动调整自己的高度,保证与superView顶部和底部的距离不变.
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5 //!< 自动调整与superView底部的距离,也就是说,与superView顶部的距离不变.
};
 
/** UIView动画选项 */
typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
    UIViewAnimationOptionLayoutSubviews            = 1 <<  0, //!< 动画过程中保证子视图跟随运动.
    UIViewAnimationOptionAllowUserInteraction      = 1 <<  1, //!< 动画过程中允许用户交互.
    UIViewAnimationOptionBeginFromCurrentState     = 1 <<  2, //!< 所有视图从当前状态开始运行.
    UIViewAnimationOptionRepeat                    = 1 <<  3, //!< 重复运行动画.
    UIViewAnimationOptionAutoreverse               = 1 <<  4, //!< 动画运行到结束点后仍然以动画方式回到初始点.
    UIViewAnimationOptionOverrideInheritedDuration = 1 <<  5, //!< 忽略嵌套动画时间设置.
    UIViewAnimationOptionOverrideInheritedCurve    = 1 <<  6, //!< 忽略嵌套动画速度设置.
    UIViewAnimationOptionAllowAnimatedContent      = 1 <<  7, //!< 动画过程中重绘视图(注意仅仅适用于转场动画).
    UIViewAnimationOptionShowHideTransitionViews   = 1 <<  8, //!< 视图切换时直接隐藏旧视图、显示新视图,而不是将旧视图从父视图移除(仅仅适用于转场动画).
    UIViewAnimationOptionOverrideInheritedOptions  = 1 <<  9, //!< 不继承父动画设置或动画类型.
    
    UIViewAnimationOptionCurveEaseInOut            = 0 << 16, //!< 动画先缓慢,然后逐渐加速.
    UIViewAnimationOptionCurveEaseIn               = 1 << 16, //!< 动画逐渐变慢.
    UIViewAnimationOptionCurveEaseOut              = 2 << 16, //!< 动画逐渐加速.
    UIViewAnimationOptionCurveLinear               = 3 << 16, //!< 动画匀速执行,默认值.
    
    UIViewAnimationOptionTransitionNone            = 0 << 20, //!< 没有转场动画效果.
    UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20, //!< 从左侧翻转效果.
    UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20, //!< 从右侧翻转效果.
    UIViewAnimationOptionTransitionCurlUp          = 3 << 20, //!< 向后翻页的动画过渡效果.
    UIViewAnimationOptionTransitionCurlDown        = 4 << 20, //!< 向前翻页的动画过渡效果.
    UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20, //!< 旧视图溶解消失显示下一个新视图的效果.
    UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20, //!< 从上方翻转效果.
    UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20, //!< 从底部翻转效果.
    
    UIViewAnimationOptionPreferredFramesPerSecondDefault     = 0 << 24, //!< 默认的帧每秒.
    UIViewAnimationOptionPreferredFramesPerSecond60          = 3 << 24, //!< 60帧每秒的帧速率.
    UIViewAnimationOptionPreferredFramesPerSecond30          = 7 << 24, //!< 30帧每秒的帧速率.
    
} NS_ENUM_AVAILABLE_IOS(4_0);
 
typedef NS_OPTIONS(NSUInteger, UIViewKeyframeAnimationOptions) {
    UIViewKeyframeAnimationOptionLayoutSubviews            = UIViewAnimationOptionLayoutSubviews, //!< 动画过程中保证子视图跟随运动.
    UIViewKeyframeAnimationOptionAllowUserInteraction      = UIViewAnimationOptionAllowUserInteraction, //!< 动画过程中允许用户交互.
    UIViewKeyframeAnimationOptionBeginFromCurrentState     = UIViewAnimationOptionBeginFromCurrentState, //!< 所有视图从当前状态开始运行.
    UIViewKeyframeAnimationOptionRepeat                    = UIViewAnimationOptionRepeat, //!< 重复运行动画.
    UIViewKeyframeAnimationOptionAutoreverse               = UIViewAnimationOptionAutoreverse, //!< 动画运行到结束点后仍然以动画方式回到初始点.
    UIViewKeyframeAnimationOptionOverrideInheritedDuration = UIViewAnimationOptionOverrideInheritedDuration, //!< 忽略嵌套动画时间设置.
    UIViewKeyframeAnimationOptionOverrideInheritedOptions  = UIViewAnimationOptionOverrideInheritedOptions, //!< 不继承父动画设置或动画类型.
    
    UIViewKeyframeAnimationOptionCalculationModeLinear     = 0 << 10, //!< 连续运算模式, 默认.
    UIViewKeyframeAnimationOptionCalculationModeDiscrete   = 1 << 10, //!< 离散运算模式.
    UIViewKeyframeAnimationOptionCalculationModePaced      = 2 << 10, //!< 均匀执行运算模式.
    UIViewKeyframeAnimationOptionCalculationModeCubic      = 3 << 10, //!< 平滑运算模式.
    UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10  //!< 平滑均匀运算模式.
} NS_ENUM_AVAILABLE_IOS(7_0);
 
typedef NS_ENUM(NSUInteger, UISystemAnimation) {
    UISystemAnimationDelete,    //!< 系统删除动画
} 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,         //!< 打开/ RW / FF等播放控制按钮
    UISemanticContentAttributeSpatial,          //!< 控制导致某种形式的定向改变UI中,如分段控制文本对齐方式或在游戏中方向键
    UISemanticContentAttributeForceLeftToRight, //!< 视图总是从左向右布局.
    UISemanticContentAttributeForceRightToLeft  //!< 视图总是从右向左布局.
} NS_ENUM_AVAILABLE_IOS(9_0);
 
@protocol UICoordinateSpace <NSObject>
 
/** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect */
- (CGRect)convertRect:(CGRect)rect toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 将rect从view中转换到当前视图中,返回在当前视图中的rect */
- (CGRect)convertRect:(CGRect)rect fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
 
/** 获取bounds */
@property (readonly, nonatomic) CGRect bounds NS_AVAILABLE_IOS(8_0);
 
@end
 
@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, UIFocusItem, CALayerDelegate>
 
/** 返回主layer所使用的类 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) Class layerClass;
#else
+ (Class)layerClass;
#endif
 
/** 通过Frame初始化UI对象 */
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
/** 用于xib初始化 */
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
 
/** 设置用户交互,默认YES允许用户交互 */
@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;
/** 控件标记(父控件可以通过tag找到对应的子控件),默认为0 */
@property(nonatomic)                                 NSInteger tag;
/** 视图图层(可以用来设置圆角效果/阴影效果) */
@property(nonatomic,readonly,strong)                 CALayer  *layer;
 
/** 返回是否可以成为焦点, 默认NO */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic,readonly) BOOL canBecomeFocused NS_AVAILABLE_IOS(9_0);
#else
- (BOOL)canBecomeFocused NS_AVAILABLE_IOS(9_0);
#endif
/** 是否可以被聚焦 */
@property (readonly, nonatomic, getter=isFocused) BOOL focused NS_AVAILABLE_IOS(9_0);
 
/** 左右滑动翻转效果 */
@property (nonatomic) UISemanticContentAttribute semanticContentAttribute NS_AVAILABLE_IOS(9_0);
 
/** 获取视图的方向 */
+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)attribute NS_AVAILABLE_IOS(9_0);
 
/** 获取相对于指定视图的界面方向 */
+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute relativeToLayoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection NS_AVAILABLE_IOS(10_0);
 
/** 返回即时内容的布局的方向 */
@property (readonly, nonatomic) UIUserInterfaceLayoutDirection effectiveUserInterfaceLayoutDirection NS_AVAILABLE_IOS(10_0);
 
@end
 
@interface UIView(UIViewGeometry)
 
/** 位置和尺寸(以父控件的左上角为坐标原点(0, 0)) */
@property(nonatomic) CGRect            frame;
 
/** 位置和尺寸(以自己的左上角为坐标原点(0, 0)) */
@property(nonatomic) CGRect            bounds;
/** 中心点(以父控件的左上角为坐标原点(0, 0)) */
@property(nonatomic) CGPoint           center;
/** 变形属性(平移\缩放\旋转) */
@property(nonatomic) CGAffineTransform transform;
/** 视图内容的缩放比例 */
@property(nonatomic) CGFloat           contentScaleFactor NS_AVAILABLE_IOS(4_0);
 
/** 是否支持多点触摸,默认NO */
@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled __TVOS_PROHIBITED;
/** 是否独占整个Touch事件,默认NO */
@property(nonatomic,getter=isExclusiveTouch) BOOL       exclusiveTouch __TVOS_PROHIBITED;
 
/** 在指定点上点击测试指定事件 */
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
/** 判断当前的点击或者触摸事件的点是否在当前的view中,默认返回YES */
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
 
/** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
/** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;
/** 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect */
- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
/** 将rect从view中转换到当前视图中,返回在当前视图中的rect */
- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;
 
/** 自动调整子视图尺寸,默认YES则会根据autoresizingMask属性自动调整子视图尺寸 */
@property(nonatomic) BOOL               autoresizesSubviews;
/** 自动调整子视图与父视图的位置,默认UIViewAutoresizingNone */
@property(nonatomic) UIViewAutoresizing autoresizingMask;
 
/** 返回“最佳”大小适合给定的大小 */
- (CGSize)sizeThatFits:(CGSize)size;
/** 调整为刚好合适子视图大小 */
- (void)sizeToFit;
 
@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;
 
/** 添加子视图(新添加的视图在subviews数组的后面, 显示在最上面) */
- (void)addSubview:(UIView *)view;
/** 插入子视图(将子视图插到siblingSubview之下) */
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
/** 插入子视图(将子视图插到siblingSubview之上) */
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;
 
/** 将子视图拉到最上面来显示 */
- (void)bringSubviewToFront:(UIView *)view;
/** 将子视图拉到最下面来显示 */
- (void)sendSubviewToBack:(UIView *)view;
 
##pragma mark - 系统自动调用(留给子类去实现)
/** 添加自视图完成后调用 */
- (void)didAddSubview:(UIView *)subview;
/** 将要移除自视图时调用 */
- (void)willRemoveSubview:(UIView *)subview;
 
/** 将要移动到新父视图时调用 */
- (void)willMoveToSuperview:(nullable UIView *)newSuperview;
/** 移动到新父视图完成后调用 */
- (void)didMoveToSuperview;
/** 将要移动到新Window时调用 */
- (void)willMoveToWindow:(nullable UIWindow *)newWindow;
/** 移动到新Window完成后调用 */
- (void)didMoveToWindow;
 
/** 判断view是否为子类 */
- (BOOL)isDescendantOfView:(UIView *)view;
/** 通过tag获得对应的子视图 */
- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag;
 
/** 对现在有布局有调整更改后,使用这个方法进行更新 */
- (void)setNeedsLayout;
/** 强制进行更新layout */
- (void)layoutIfNeeded;
 
/** 控件的frame发生改变的时候就会调用,一般在这里重写布局子控件的位置和尺寸 */
- (void)layoutSubviews;
 
/** 设置view之间的间距,该属性只对autolayout布局有效 */
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
/** 是否将当前视图的间距和父视图相同,默认是NO */
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0);
/** 改变view的layoutMargins这个属性时,会触发这个方法 */
- (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);
 
/** 视图间距引导 */
@property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0);
 
/** 获取此区域的内的布局引导 */
@property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide  NS_AVAILABLE_IOS(9_0);
@end
 
@interface UIView(UIViewRendering)
 
/** 重写drawRect方法,在可以这里进行绘图操作。*/
- (void)drawRect:(CGRect)rect;
 
/** 标记整个视图的边界矩形需要重绘, 调用这个方法会自动调用drawRect方法 */
- (void)setNeedsDisplay;
/** 标记在指定区域内的视图的边界需要重绘, 调用这个方法会自动调用drawRect方法 */
- (void)setNeedsDisplayInRect:(CGRect)rect;
 
/** 是否裁剪超出Bounds范围的子控件,默认NO */
@property(nonatomic)                 BOOL              clipsToBounds;
/** 设置背景颜色,默认nil */
@property(nullable, nonatomic,copy)  UIColor          *backgroundColor UI_APPEARANCE_SELECTOR;
/** 设置透明度(范围0.0~1.0),默认1.0 */
@property(nonatomic)                 CGFloat           alpha;
/** 设置是否不透明,默认YES不透明 */
@property(nonatomic,getter=isOpaque) BOOL              opaque;
/** 视图重绘前是否先清理以前的内容,默认YES */
@property(nonatomic)                 BOOL              clearsContextBeforeDrawing;
/** 设置是否隐藏,默认NO不隐藏 */
@property(nonatomic,getter=isHidden) BOOL              hidden;
/** 内容显示的模式,默认UIViewContentModeScaleToFill */
@property(nonatomic)                 UIViewContentMode contentMode;
/** 拉伸属性,如图片拉伸 */
@property(nonatomic)                 CGRect            contentStretch NS_DEPRECATED_IOS(3_0,6_0) __TVOS_PROHIBITED;
 
/** 蒙板view */
@property(nullable, nonatomic,strong)          UIView           *maskView NS_AVAILABLE_IOS(8_0);
 
/** 改变应用程序的外观的颜色。默认为nil */
@property(null_resettable, nonatomic, strong) UIColor *tintColor NS_AVAILABLE_IOS(7_0);
 
/** 可以使tintColor变暗,因此整个视图层次变暗 */
@property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode NS_AVAILABLE_IOS(7_0);
 
/** 覆盖这个方法的目的是为了当tintColor改变的时候自定义一些行为 */
- (void)tintColorDidChange NS_AVAILABLE_IOS(7_0);
 
@end
 
@interface UIView(UIViewAnimation)
 
/** 开始动画 */
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;
/** 提交动画 */
+ (void)commitAnimations;
 
/** 设置动画代理, 默认nil */
+ (void)setAnimationDelegate:(nullable id)delegate;
/** 动画将要开始时执行方法(必须要先设置动画代理), 默认NULL */
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;
/** 动画已结束时执行方法(必须要先设置动画代理), 默认NULL */
+ (void)setAnimationDidStopSelector:(nullable SEL)selector;
/** 设置动画时长, 默认0.2秒 */
+ (void)setAnimationDuration:(NSTimeInterval)duration;
/** 动画延迟执行时间, 默认0.0秒 */
+ (void)setAnimationDelay:(NSTimeInterval)delay;
/** 设置在动画块内部动画属性改变的开始时间, 默认now ([NSDate date]) */
+ (void)setAnimationStartDate:(NSDate *)startDate;
/** 设置动画曲线, 默认UIViewAnimationCurveEaseInOut */
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;
/** 动画的重复播放次数, 默认0 */
+ (void)setAnimationRepeatCount:(float)repeatCount;
/** 设置是否自定翻转当前的动画效果, 默认NO */
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
/** 设置动画从当前状态开始播放, 默认NO */
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;
 
/** 在动画块中为视图设置过渡动画 */
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
 
/** 设置是否激活动画 */
+ (void)setAnimationsEnabled:(BOOL)enabled;
/** 返回一个布尔值表示动画是否结束 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL areAnimationsEnabled;
#else
+ (BOOL)areAnimationsEnabled;
#endif
/** 先检查动画当前是否启用,然后禁止动画,执行block内的方法,最后重新启用动画,而且这个方法不会阻塞基于CoreAnimation的动画 */
+ (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0);
 
/** 当前动画的持续时间 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) NSTimeInterval inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#else
+ (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#endif
 
@end
 
@interface UIView(UIViewAnimationWithBlocks)
 
/** 用于对一个或多个视图的改变的持续时间、延时、选项动画完成时的操作 */
+ (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);
 
/** 用于对一个或多个视图的改变的持续时间、选项动画完成时的操作,默认:delay = 0.0, options = 0 */
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
 
/** 用于对一个或多个视图的改变的持续时间内动画完成时的操作,默认:delay = 0.0, options = 0, completion = NULL */
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0);
 
/** 使用与物理弹簧运动相对应的定时曲线执行视图动画 */
+ (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
 
/** 在一个或多个视图上执行指定的系统提供的动画,以及定义的可选并行动画 */
+ (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
 
/** UIView的关键帧动画 */
@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);
/** 添加指定开始时间、持续时间的关键帧动画(起始和持续时间是0.0和1.0之间的值) */
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0);
 
@end
 
@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);
 
/** 开始一个手势识别器 */
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer NS_AVAILABLE_IOS(6_0);
 
@end
 
@interface UIView (UIViewMotionEffects)
 
/** 添加运动效果,当倾斜设备时视图稍微改变其位置 */
- (void)addMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);
 
/** 移除运动效果 */
- (void)removeMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);
 
/** 所有添加的运动效果 */
@property (copy, nonatomic) NSArray<__kindof UIMotionEffect *> *motionEffects NS_AVAILABLE_IOS(7_0);
 
@end
 
 
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
    UILayoutConstraintAxisHorizontal = 0,   //!< 水平约束.
    UILayoutConstraintAxisVertical = 1      //!< 竖直约束.
};
 
 
@interface UIView (UIConstraintBasedLayoutInstallingConstraints)
 
/** 获取所有约束 */
@property(nonatomic,readonly) NSArray<__kindof NSLayoutConstraint *> *constraints NS_AVAILABLE_IOS(6_0);
 
/** 添加一个约束 */
- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
/** 添加多个约束 */
- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
/** 移除一个约束 */
- (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
/** 移除多个约束 */
- (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
@end
 
 
@interface UIView (UIConstraintBasedLayoutCoreMethods)
/** 更新视图和其子视图的约束 */
- (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0);
/** 为视图更新约束,可以重写这个方法来设置当前view局部的布局约束 */
- (void)updateConstraints NS_AVAILABLE_IOS(6_0) NS_REQUIRES_SUPER;
/** 视图的约束是否需要更新 */
- (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0);
/** 设置视图的约束需要更新,调用这个方法,系统会调用updateConstraints去更新布局 */
- (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0);
@end
 
 
@interface UIView (UIConstraintBasedCompatibility)
 
/** 是否启用自动布局约束,默认YES. IB默认是NO */
@property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0);
 
/** 是否使用约束布局 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
#else
+ (BOOL)requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
#endif
 
@end
 
 
@interface UIView (UIConstraintBasedLayoutLayering)
 
/** 返回给定框架的视图的对齐矩阵 */
- (CGRect)alignmentRectForFrame:(CGRect)frame NS_AVAILABLE_IOS(6_0);
/** 返回给定对齐矩形的视图的frame */
- (CGRect)frameForAlignmentRect:(CGRect)alignmentRect NS_AVAILABLE_IOS(6_0);
 
/** 返回从视图的frame上定义的对齐矩阵的边框 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) UIEdgeInsets alignmentRectInsets NS_AVAILABLE_IOS(6_0);
#else
- (UIEdgeInsets)alignmentRectInsets NS_AVAILABLE_IOS(6_0);
#endif
 
/** 返回满足基线约束条件的视图 */
- (UIView *)viewForBaselineLayout NS_DEPRECATED_IOS(6_0, 9_0, "Override -viewForFirstBaselineLayout or -viewForLastBaselineLayout as appropriate, instead") __TVOS_PROHIBITED;
 
/** 返回用于满足第一基线约束的视图 */
@property(readonly,strong) UIView *viewForFirstBaselineLayout NS_AVAILABLE_IOS(9_0);
 
/** 返回用于满足上次基线约束的视图 */
@property(readonly,strong) UIView *viewForLastBaselineLayout NS_AVAILABLE_IOS(9_0);
 
 
UIKIT_EXTERN const CGFloat UIViewNoIntrinsicMetric NS_AVAILABLE_IOS(6_0); // -1
/** 返回接收对象的原本大小 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) CGSize intrinsicContentSize NS_AVAILABLE_IOS(6_0);
#else
- (CGSize)intrinsicContentSize NS_AVAILABLE_IOS(6_0);
#endif
/** 废除视图原本内容的size */
- (void)invalidateIntrinsicContentSize NS_AVAILABLE_IOS(6_0);
 
/** 设置当视图要变大时,视图的压缩改变方式,返回一个优先权(确定view有多大的优先级阻止自己变大) */
- (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)
/** 返回满足持有约束的视图的size */
- (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)
 
/** 此视图拥有布局向导对象的数组 */
@property(nonatomic,readonly,copy) NSArray<__kindof UILayoutGuide *> *layoutGuides NS_AVAILABLE_IOS(9_0);
 
/** 向视图中添加布局向导 */
- (void)addLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
 
/** 向视图中添加布局向导 */
- (void)removeLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
@end
 
@class NSLayoutXAxisAnchor,NSLayoutYAxisAnchor,NSLayoutDimension;
@interface UIView (UIViewLayoutConstraintCreation)
/** 布局视图的前缘框的布局锚点 */
@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
 
@interface UIView (UIConstraintBasedLayoutDebugging)
 
/** 获得实体在不同方向上所有的布局约束 */
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
 
/** 可以知道当前视图的布局是否会有歧义 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);
#else
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);
#endif
 
/** 这个方法会随机改变视图的layout到另外一个有效的layout。这样我们就可以很清楚的看到哪一个layout导致了整体的布局约束出现了错误,或者我们应该增加更多的布局约束 */
- (void)exerciseAmbiguityInLayout NS_AVAILABLE_IOS(6_0);
@end
 
/** 约束调试,只在DEBUG环境下被调用 */
@interface UILayoutGuide (UIConstraintBasedLayoutDebugging)
 
/** 获得实体在不同方向上所有的布局约束 */
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(10_0);
 
/** 可以知道当前视图的布局是否会有歧义 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
#else
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
#endif
@end
 
#pragma mark - View状态保存恢复
@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
 
#pragma mark - View快照
@interface UIView (UISnapshotting)
/** 将当前显示的view截取成一个新的view */
- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
/** 缩放一个view默认是从中心点进行缩放的 */
- (nullable UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0);
/** 屏幕快照 */
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
@end


2. UIView 常用的属性

2.1 UIView的圆角加阴影效果的实现

削圆角一般有两种方式,一种是直接用layer.cornerRadius来设置,我们知道的一般都是下面两行代码一起使用来实现圆角:

self.layer.cornerRadius = 10;
self.layer.masksToBounds=YES;

但是只要self.layer.masksToBounds=YES;有这句,投影的效果就出不来。
还有一种性能比较好的圆角设置方式,就是用UIBezierPath来设置,我试过用这个来设置圆角的话,投影一样也出不来。
还有在网上看到了加一层layer的,大体思路就是self.layer来设置圆角,新写一个layer来设置投影,然后把layer放到self.layer上,我试了之后发现没什么效果,而且偏移会很明显的看出来,但不是以投影的方式出现。

-(instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = kUIColorFromRGB(0x4b4773);
        //v.layer.masksToBounds=YES;这行去掉
        self.layer.cornerRadius = 10;
        self.layer.shadowColor = kUIColorFromRGB1(0x000000, 1).CGColor;
        self.layer.shadowOffset = CGSizeMake(2, 5);
        self.layer.shadowOpacity = 0.5;
        self.layer.shadowRadius = 5;

    }
    return self;
}

效果:
在这里插入图片描述

2.2 UIView 属性

UIView :基本属性,tag、layer、可否交互等设置
以下是分类UIView ()
UIViewGeometry : 几何特征 位置 【frame 、bound 、center 、等】
UIViewHierarchy : 层级
UiViewRendering : 渲染/打底
UIViewAnimation : 动画
UIViewAnimationWithBlocks : 动画回掉
UIViewKeyframeAnimation : 关键帧动画
UIViewGestureRecongizers : 手势识别
UIViewMotionEffects : 运动影响

与约束有关的

UIConstraintBasedInstallingConstraints
UIConstraintBasedLayoutCoreMethod
UIConstraintBasedCompatibility
UIConstraintBasedLayoutLayering
UIConstraintBasedLayoutFittingSize
UIConstraintBasedLayoutDebugging

2.2.1 UIView 几何属性

//视图对象使用frame, bounds和center属性来跟踪它的尺寸和位置:
//  frame属性指定了在视图的尺寸和在父视图中的位置。
//  center属性指定了视图的中点在父视图的位置。
//  bounds属性指定了在视图本地坐标系统中视图的尺寸。默认原点是(0,0)。
//  可以通过center和bounds计算得到frame,反之同理。frame.origin.x == center.x - bounds.size.width / 2; frame.size == bounds.size;
//  transform属性用于视图的动画,通过操作transform实现视图的旋转、缩放。  
      - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
      - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

//       这两个方法主要用于响应者链, 用于确定视图是否为第一响应者,当用户碰触屏幕的时候系统会生成一个碰触点。为了确认哪个控件是这个碰触的第一响应者系统会调用window的hitTest方法,hitTest会调用pointInside方法判断触碰点是否在当前视图的区域内。如果在返回YES,则调用该试图所有子试图的hitTest方法;如果不在则返回NO,hitTest函数直接返回nil;如果pointInside方法返回YES,且没有子视图或者子视图的hiteTest方法返回都为nil则此视图为第一响应者,第一响应者是响应者链的开端
//      点转换方法。比如一个view上有一个button,在button上有一个点p,这个点相对button的坐标知道了,想知道这个点在这个view上的坐标,用这两个api去转换。

      - (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
      [button convertPoint:p toView:view] 这样得到view上的点。
      - (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view
      [view convertPoint:p fromView:button];

//      同点转换方法,转换一个矩形
      - (CGRect)convertRect:(CGRect)rect toView:(UIView *)view
      - (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view
     - (CGSize)sizeThatFits:(CGSize)size

 // 返回最合适的尺寸,size是首选尺寸。只返回尺寸不会改变尺寸,如一个UILabel的text发生改变,需要UILabel的bounds调整,调用这个方法会返回一个最合适的值。
  - (void)sizeToFit
 // 按照sizeThatFits的返回值重新设置视图的bounds。
  
//      autoresizingMask 当父视图的bounds发生改变时通过这个属性决定如何调整自己的frame。缺省的值为UIViewAutoresizingNone,表示当父视图bound变化时,自己相对于父视图的frame不变。可以通过|设置多个规则,如:UIViewAutoresizingFlexibleWidth  | UIViewAutoresizingFlexibleHeight       

  UIViewAutoresizingNone               
  UIViewAutoresizingFlexibleLeftMargin  // 到屏幕左边的距离随着父视图的宽度按比例改变      
  UIViewAutoresizingFlexibleWidth  //视图的宽度随着父视图的宽度按比例改变      
  UIViewAutoresizingFlexibleRightMargin   //到屏幕右边的距离随着父视图的宽度按比例改变      
  UIViewAutoresizingFlexibleTopMargin  //到屏幕顶部的距离随着父视图的高度按比例改变      
  UIViewAutoresizingFlexibleHeight     //视图的高度随着父视图的高度等比例改变      
  UIViewAutoresizingFlexibleBottomMargin
   autoresizesSubviews //默认值YES,如果设置为NO那么该视图的所有直接子视图的frame自动调整行为将被忽略,也就是说无论子视图的autoresizingMask属性设置成什么都相当于置为UIViewAutoresizingNone。

2.2.2 UIView 渲染属性

clipsToBounds 当值为YES时,子视图如果超过了当前视图的区域,超出的部分就会被裁掉。默认值是NO,也就是说当子视图显示区域大于主视图的时候还是正常显示不会裁剪。

backgroundColor 设置背景色

alpha 设置视图的透明度,当为1时不透明,为0时完全透明,既隐藏。默认值是1。alpha值会影响到子视图。如果想让父视图半透明而子视图不受影响可以设置父视图的backgroundColor = [UIColor colorWithWhite:0 alpha:0.8],这样就ok了。

opaque 给绘图系统提供一个性能优化开关。如果该值为YES,那么绘图在绘制该视图的时候把整个视图当作不透明对待。这样,绘图系统在执行绘图过程中会优化一些操作并提升系统性能;如果是设置为NO, 绘图系统将其和其他内容平等对待,不去做优化操作。为了性能方面的考量,默认被置为YES(意味着‘优化’)。

一个不透明视图需要整个边界里面的内容都是不透明的。基于这个原因,opaque设置为YES,要求对应的alpha必须为1.0。如果一个UIView实例opaque被设置为YES, 而同时它又没有完全填充它的边界(bounds),或者它包含了整个或部分的透明的内容视图,那么将会导致未知的结果。

clearsContextBeforeDrawing 决定绘制前是否清屏,默认为YES。用于提高描画性能,特别是在可滚动的视图中。当这个属性被设置为YES时,UIKIt会在调用drawRect:方法之前,把即将被该方法更新的区域填充为透明的黑色。将这个属性设置为NO可以取消相应的填充操作,view中原有内容会保留。

hidden 视图是否隐藏,默认为NO(显示),YES为隐藏。

contentMode 视图内容的填充方式。类型是UIViewContentMode。默认值是UIViewContentModeScaleToFill,填充到整个视图区域,不等比例拉伸。

typedef NS_ENUM(NSInteger, UIViewContentMode) {
  UIViewContentModeScaleToFill,     填充到整个视图区域,不等比例拉伸
  UIViewContentModeScaleAspectFit, 长宽等比填充视图区域,当某一个边到达视图边界的时候就不再拉伸,保证内容的长宽比是不变的同时尽可能的填充视图区域。
  UIViewContentModeScaleAspectFill, 长宽等比填充视图区域,当某一个边到达视图边界的时候还继续拉伸,直到另一个方向达到视图边界。内容的长宽比不变的同时填满整个视图区域,不显示超过的部分。
  UIViewContentModeRedraw, 重绘视图边界
  UIViewContentModeCenter, 视图居中
  UIViewContentModeTop,         视图顶部对齐
  UIViewContentModeBottom, 视图底部对齐
   UIViewContentModeLeft, 视图左侧对齐
  UIViewContentModeRight, 视图右侧对齐
   UIViewContentModeTopLeft, 视图左上角对齐
  UIViewContentModeTopRight, 视图右上角对齐
  UIViewContentModeBottomLeft, 视图左下角对齐
  UIViewContentModeBottomRight, 视图右下角对齐
  };

以上模式中凡是没有带scale的,内容bounds超出视图bounds时只有未超出部分才在视图bounds中显示。
autoresizingMask 当父视图的bounds发生改变时通过这个属性决定如何调整自己的frame。缺省的值为UIViewAutoresizingNone,表示当父视图bound变化时,自己相对于父视图的frame不变。可以通过|设置多个规则,如:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
 enum {
  UIViewAutoresizingNone = 0,
  UIViewAutoresizingFlexibleLeftMargin = 1 << 0, 到屏幕左边的距离随着父视图的宽度按比例改变
  UIViewAutoresizingFlexibleWidth = 1 << 1, 视图的宽度随着父视图的宽度按比例改变
  UIViewAutoresizingFlexibleRightMargin = 1 << 2, 到屏幕右边的距离随着父视图的宽度按比例改变
  UIViewAutoresizingFlexibleTopMargin = 1 << 3, 到屏幕顶部的距离随着父视图的高度按比例改变
  UIViewAutoresizingFlexibleHeight = 1 << 4, 视图的高度随着父视图的高度等比例改变
  UIViewAutoresizingFlexibleBottomMargin = 1 << 5
  };
  typedef NSUInteger UIViewAutoresizing;
  autoresizesSubviews 默认值YES,如果设置为NO那么该视图的所有直接子视图的frame自动调整行为将被忽略,也就是说无论子视图的autoresizingMask属性设置成什么都相当于置为UIViewAutoresizingNone。

contentStretch 用于制定哪部分是可拉伸的,取值在 0.0到1.0之间。下面用一个例子解释contentStretch是如何工作的。

[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。

- (void)setNeedsDisPlay

调用此方法通知系统view需要重新绘制,会异步自动调用drawRect方法。

- (void)setNeedsDisplayInRect:(CGRect)rect

同样异步调用drawRect方法。在一次运行循环(run loop)中无论调用setNeedsDisplay或setNeedsDisplayInRect多少次,只调用drawRect一次。也是从减少资源开销的角度考虑的。

- (void)drawRect:(CGRect)rect

此方法的缺省实现是空。子类使用原生的绘制技术(Core Graphics and UIKit)绘制内容时应该重写此方法,在方法里面写出自己的drawing code。如果view设置自己的内容用其他的方法,则不需要去重写此方法。如果直接从UIView对象继承,实现此方法不需要call super。然而如果从其他的UIView对象继承,则应该调用super。当view 第一次显示或者当view的可视的一部分无效时,此方法会调用。此方法不能直接被调用。调用setNeedsDisplay 或者 setNeedsDisplayInRect: 方法会触发重新绘制

2.2.3 UIView 视图层次

//UIView除了提供自己的内容外,还可以作为一个视图容器。当一个视图包含其他视图时,就在两者之间建立了一个父子关系。在视觉上子视图隐藏了父视图的内容,如果一个子视图是完全不透明的,那么子视图所在区域就完全遮挡了父视图的相应区域。如果子视图是部分透明的那么两个视图在显示上就混合在了一起。父子视图关系也会影响一些视图行为,改变父视图的尺寸也会相应的改变子视图的尺寸。隐藏父视图,改变父视图的alpha值,转换父视图都会影响到子视图。

 // UIView通过NSArray管理子视图的。通过属性subviews可以访问视图的所有子视图。通过NSArray的特点可以得出两点:

  //(1)子视图的引用计数会+1,当父视图释放的时候子视图的引用计数-1。

  //(2)子视图是有序的,后加入的子视图会叠在上一个子视图之上。

  - (void)addSubview:(UIView *)view 方法增加一个子视图。

  //操作子视图的方法:

  - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index                   //在指定的层级插入一个子视图。最底层是0;最顶层就是subviews count,相当于addSubview

  - (void)insertSubview:(UIView *)b belowSubview:(UIView *)c                   // b成为子视图并且在已有的子视图c的下面

  - (void)insertSubview:(UIView *)b aboveSubview:(UIView *)c                                  // b成为子视图并且在已有的子视图c的上面

  - (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2  //交换两个子视图的层级。

  - (void)bringSubviewToFront:(UIView *)view                                                                          // 视图上升到最顶层。                                               

  - (void)sendSubviewToBack:(UIView *)view                                                                             //视图下降到最底层

  - (void)removeFromSuperview                                                                                                 //删除所有子视图。

  //superview 属性用于获取当前视图的父视图。

   

  - (void)setNeedsLayout

  //调用此方法通知系统view的内容需要重新绘制,会异步调用layoutSubviews方法,view会在下一个drawing周期绘制。如果只是简单的改变view的几何形状或者当前视图并没有在窗口中显示,系统可能不会调用layoutSubviews方法。

  - (void)layoutIfNeeded

  调用此方法通知系统view的内容需要重新绘制,调用layoutSubviews方法。与setNeedLayout不同的时不会等到下一个drawing周期,会立即调用layoutSubviews方法。

  - (void)layoutSubviews

  //此方法的缺省实现是空。子类可以去重写此方法当需要更精确的subviews布局。当subviews的autoresizes行为不能满足要求时才去重写此方法。可以在实现中直接设置subviews的frame。此方法不能被直接调用。如果想要在下一个drawing周期去更新view布局,应该调用setNeedsLayout方法;如果想立即更新view的布局,应该调用layoutIfNeeded方法。

  //layoutSubviews之所以不能被直接调用的原因可能是系统在绘制时需要进行一些操作并判断需不需要调用layoutSubviews的方法,并且在一次运行循环(run loop)中无论调用多少次setNeedsLayout都只调用一次layoutSubviews。这样就避免了资源的重复调用。

2.2.4 UIView 视图绘制周期

UIView类使用一个点播绘制模型来展示内容,当一个视图第一次出现在屏幕前,系统会要求它绘制自己的内容,在该流程中系统会创建一个快照,这个快照是出现在屏幕中得视图内容的可见部分。如果从来没有改变视图的内容,则这个视图绘制的方法drawRect可能永远都不会再被调用。这个快照图像在大部分涉及到视图的操作中被重用。

如果改变了视图的内容,系统也不会马上重绘视图。使用setNeedsDisPlay或setNeedsDisplayInRect方法废除该视图同时让系统在稍后重绘视图。系统等待当前运行循环(run loop)结束,然后开始重绘。这个延迟可以用来废除多个视图、增加或删除视图、隐藏、重设大小。所有的改变会在稍后一起生效。

什么是run loop?个人认为可以简单的理解为一个事件的处理过程。例如:用户点击屏幕会产生两个run loop。当用户按下的时候会产生一个run loop;当用户抬起的时候会产生另一个run loop。

如果在一个run loop中调用setNeedsDisplayInRect方法,系统会保证在这个run loop结束前调用一次drawRect方法;无论在当前run loop调用setNeedsDisplayInRect方法多少次都只调用一次drawRect。setNeedsDisplayInRect方法如果在一个run loop中刷新不同的区域,最后drawRect方法会将这些区域组合起来一起刷新,组合原则用最小的矩形圈起来所有区域,并刷新这个区域。如果刷新区域是屏幕左下角和右上角两个点,有可能刷新整个屏幕。

UIWindow

  //UIWindow对象是所有UIView的父视图,UIWindow类是UIView的子类,可以看作是特殊的UIView。一般应用程序只有一个UIWindow对象,即使有多个UIWindow对象,也只有一个UIWindow可以接受到用户的触屏事件。UIWindow初始化在appDelegate里。 [self.window makeKeyAndVisible]方法,使window显示。

 

  UIScreen

 // UIScreen用于获取设备屏幕的尺寸。

  [UIScreen mainScreen].bounds //获取整个屏幕的大小;当应用程序有状态栏时,返回值:{{0, 0}, {320, 480}}

  [UIScreen mainScreen].applicationFrame //获取应用程序窗口的大小;当应用程序有状态栏时,返回值:{{0, 20}, {320, 460}}

  

  UIViewController

  //UIViewController是MVC中的C控制器,控制管理UIView。UIViewController同UIView的关系相当于相框和相片的关系,相框可以操作相片、替换相片、决定相片的显隐藏,反之则不行。UIView工作在第一线,向用户展示表现的内容,并接受用户的交互;UIViewController负责两个方面,数据和行为,通过数据更新view,通过行为处理用户交互操作,注意这里是“处理”而不是“响应”。

  //UIViewController同UIView一样继承与UIResponder,所以同样处于响应者链上,同样可以接收触碰等用户事件。

 // 可以通过下面的方法获得UIView所属的UIViewController
 

2.2.5 UIViewGeometry :几何位置

该分类主要决定该View的几何与位置

@interface UIView(UIViewGeometry)  
@property(nonatomic) CGRect            frame;    // 当前视图的边界,包括大小和原点,这里是在父视图的坐标系下 (当处于动画中,或者不是最后显示的时候,建议使用bounds和center来确定位置)  
@property(nonatomic) CGRect            bounds;      // 当前视图的边界,包括大小和原点,这里是在自己的坐标系下  
@property(nonatomic) CGPoint           center;      // 当前视图的中心,并制定是在父视图的坐标系下  
@property(nonatomic) CGAffineTransform 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;

2.2.6 UIViewHierarchy : 层级

该分类主要用于管理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);  

2.2.7 UiViewRendering : 渲染/打底

该分类主要用于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 

2.2.7 UiView 动画相关属性

2.2.7.1 UIViewAnimation : 动画

该分类主要设置一些动画的方法,对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  

2.2.7.2 UIViewAnimationWithBlocks : 动画回掉

动画设置的回掉,可以设置具体怎么实现动画。

@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  

2.2.7.3 UIViewKeyframeAnimation : 关键帧动画

该类是苹果公司为了解决动画部分的代码叠层和代码量过多问题。

@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 

2.2.8 UiView 手势属性

UIViewGestureRecognizers : 手势识别

@interface UIView (UIViewGestureRecognizers)  
  
@property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers;    // 当前视图手势集合  
  
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;       // 添加手势  
- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;        // 移除手势  
  
  
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;      // 通过返回值决定是否识别此手势  
  
@end

2.2.9 UIViewMotionEffects : 运动影响

@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

2.2.10 UIView 约束

UIConstraintBasedInstallingConstraints

UIConstraintBasedLayoutCoreMethod

UIConstraintBasedCompatibility

UIConstraintBasedLayoutLayering

UIConstraintBasedLayoutFittingSize

UIConstraintBasedLayoutDebugging

 UILayoutGuideSuport :

2.3 UIView 基本定义和响应链

2.3.1基本定义

基本定义主要包含初始化、tag、交互性、layer层

@interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusEnvironment>  


+ (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);

从定义可以看出,UIView是基于UIResponder的,所有具有响应功能,可以处理点击事件(Touch Events)、运动事件(motion Events)、远程控制事件(Remote Control Events )只有程序在强制退出和来电时才会调用取消点击事件,所有继承UIResponder的子类都可以直接响应事件,称为响应者。

2.3.2iOS的事件响应链

当有点击事件发生时,系统会为其创建一个含点击信息的UITouch和UIEVent的实例,然后找到当前程序,逐级寻找能响应这个时间的对象,直到没有响应者为止,一般响应链寻找顺序如下图:

在这里插入图片描述

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值