CALayer 一般是作为 view 的属性出现,用于管理 view 的具体视觉显示效果。一般来说,简单的显示效果,如背景颜色等,可以直接在 view 上设置,而图层操作可以实现视觉效果的精细控制。
//创建图层
+ (instancetype)layer;
- (instancetype)init;
- (instancetype)initWithLayer:(id)layer;
//获取当前显示的图层
- (instancetype)presentationLayer;
//内容属性,默认为 nil ,用于存放图层显示的内容
//虽然是id类型,但只有 CGImage 和 NSImage 对象生效,其他情况显示白板
//如果存在复杂的 view 或图层操作,则应避免设置这个属性
@property(strong) id contents;
@property CGRect contentsRect;
@property CGRect contentsCenter;
//管理图层的生命周期
@property(weak) id<CALayerDelegate> delegate;
- (void)drawInContext:(CGContextRef)ctx;//绘制时调用
- (void)display;//加载图层内容,会调用delegate的displayLayer:方法,没实现则调用自己的drawInContext:方法
//显示属性
@property float opacity;
@property(getter=isHidden) BOOL hidden;
@property CGColorRef backgroundColor;
@property BOOL masksToBounds; //超出范围的子图层是否隐藏
@property(strong) __kindof CALayer *mask; //该属性指向的图层与原图层的重叠部分不显示,受透明度影响,用于图层镂空
@property(getter=isDoubleSided) BOOL doubleSided;//图层旋转时背面是否显示
@property CGFloat cornerRadius; //圆角半径,可以和masksToBounds属性配合使用
@property CACornerMask maskedCorners; //选择哪几个角是圆角
//描边属性
@property CGFloat borderWidth;
@property CGColorRef borderColor;
//阴影属性
@property float shadowOpacity;
@property CGFloat shadowRadius;
@property CGSize shadowOffset;
@property CGColorRef shadowColor;
@property CGPathRef shadowPath; //阴影形状
//位置属性
@property CGRect frame;
@property CGRect bounds;
@property CGPoint position; //frame的origin部分
@property CGFloat zPosition;//z轴位置,影响图层的层叠顺序
//变换
@property CATransform3D transform;
@property CATransform3D sublayerTransform;
//获取和设置仿射变换的(平移、旋转、缩放)的值
- (CGAffineTransform)affineTransform;
- (void)setAffineTransform:(CGAffineTransform)m;
//子图层相关
@property(copy) NSArray<__kindof CALayer *> *sublayers;
@property(readonly) CALayer *superlayer;
- (void)addSublayer:(CALayer *)layer;
- (void)removeFromSuperlayer;
- (void)insertSublayer:(CALayer *)layer atIndex:(unsigned int)idx;
- (void)insertSublayer:(CALayer *)layer below:(CALayer *)sibling;
- (void)insertSublayer:(CALayer *)layer above:(CALayer *)sibling;
- (void)replaceSublayer:(CALayer *)oldLayer with:(CALayer *)newLayer;
//在图层数组中操作建议配合名字属性
@property(copy) NSString *name;
//更新图层
- (void)setNeedsDisplay; //将图层设定为需要更新
- (void)setNeedsDisplayInRect:(CGRect)r; //将图层的指定部位设定为需要更新
@property BOOL needsDisplayOnBoundsChange; //当bounds改变时,系统自动调用setNeedsDisplay方法
- (void)displayIfNeeded; //强制更新,不推荐
- (BOOL)needsDisplay; //返回图层是否需要更新
//子图层管理
@property(strong) id<CALayoutManager> layoutManager;
- (void)setNeedsLayout; //图层的bounds或者子图层改变时自动调用,会在下一个循环中调用layoutSublayers方法
- (void)layoutSublayers; //会调用layoutManager的layoutSublayersOfLayer:方法
- (void)layoutIfNeeded; //该方法调用后,会回溯祖先直到不需要重绘的图层,然后进行重绘
- (BOOL)needsLayout;
//动画相关方法
- (void)addAnimation:(CAAnimation *)anim forKey:(NSString *)key;
- (__kindof CAAnimation *)animationForKey:(NSString *)key;
- (void)removeAllAnimations;
- (void)removeAnimationForKey:(NSString *)key;
- (NSArray<NSString *> *)animationKeys;
用于绘制直线、曲线、圆、矩形等简单图形,也可以定义包含直线段和曲线段的复杂多边形。
本质上是绘制点在屏幕上的运动轨迹,同时可以附以填充等效果。
//初始化
+ (instancetype)bezierPath;
+ (instancetype)bezierPathWithRect:(CGRect)rect;
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
//圆角矩形
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect
cornerRadius:(CGFloat)cornerRadius;
//部分圆角的矩形
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect
byRoundingCorners:(UIRectCorner)corners
cornerRadii:(CGSize)cornerRadii;
//圆弧
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center
radius:(CGFloat)radius
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
clockwise:(BOOL)clockwise;
+ (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;
//创建一个现存Path的反向Path
- (UIBezierPath *)bezierPathByReversingPath;
//绘图控制
- (void)moveToPoint:(CGPoint)point; //移动当前点
- (void)addLineToPoint:(CGPoint)point; //连接当前点与目标点
//添加圆弧
- (void)addArcWithCenter:(CGPoint)center
radius:(CGFloat)radius
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
clockwise:(BOOL)clockwise;
//添加曲线,效果参考开发手册
- (void)addCurveToPoint:(CGPoint)endPoint
controlPoint1:(CGPoint)controlPoint1
controlPoint2:(CGPoint)controlPoint2;
//关闭路径,即连接路径的首尾
- (void)closePath;
- (void)removeAllPoints;
//添加多条路径
- (void)appendPath:(UIBezierPath *)bezierPath;
//获取当前状态
@property(nonatomic) CGPathRef CGPath;
- (CGPathRef)CGPath;
@property(nonatomic, readonly) CGPoint currentPoint;
//视觉效果
@property(nonatomic) CGFloat lineWidth;
@property(nonatomic) CGFloat flatness; //曲线的平滑度
//虚线效果
- (void)setLineDash:(const CGFloat *)pattern
count:(NSInteger)count
phase:(CGFloat)phase;
- (void)getLineDash:(CGFloat *)pattern
count:(NSInteger *)count
phase:(CGFloat *)phase;
//渲染方法
- (void)fill; //填充,默认会关闭路径
- (void)stroke; //描边
- (void)applyTransform:(CGAffineTransform)transform;
用于呈现简单文本。
//基本属性
@property(nullable, nonatomic, copy) NSString *text;
@property(nonatomic, strong) UIFont *font;
@property(nonatomic, strong) UIColor *textColor;
@property(nonatomic) NSTextAlignment textAlignment;
@property(nonatomic) NSLineBreakMode lineBreakMode; //文本超出控件范围时的显示效果
@property(nonatomic, getter=isEnabled) BOOL enabled;//是否显示文本
@property(nonatomic) BOOL adjustsFontSizeToFitWidth;//字体大小适应宽度
@property(nonatomic) CGFloat minimumScaleFactor; //与上面的属性配合,最小缩放大小
@property(nonatomic) NSInteger numberOfLines; //最大显示行数
@property(nullable, nonatomic, strong) UIColor *highlightedTextColor;
@property(nonatomic, getter=isHighlighted) BOOL highlighted;
@property(nullable, nonatomic, strong) UIColor *shadowColor;
@property(nonatomic) CGSize shadowOffset;
//获取控件大小,自适应行数
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines;
- (void)drawTextInRect:(CGRect)rect;
@property(nonatomic) BOOL clipsToBounds;
//委托,用于管理输入行为的生命周期
@property(nullable, nonatomic, weak) id<UITextFieldDelegate> delegate;
//相关通知
const NSNotificationName UITextFieldTextDidBeginEditingNotification;
const NSNotificationName UITextFieldTextDidChangeNotification;
const NSNotificationName UITextFieldTextDidEndEditingNotification;
//视觉属性
@property(nullable, nonatomic, copy) NSString *text;
@property(nullable, nonatomic, copy) NSString *placeholder;//未输入任何字符时的占位符
@property(nullable, nonatomic, strong) UIFont *font;
@property(nullable, nonatomic, strong) UIColor *textColor;
@property(nonatomic) NSTextAlignment textAlignment;
@property(nonatomic) UITextBorderStyle borderStyle;
@property(nullable, nonatomic, strong) UIImage *background;
@property(nullable, nonatomic, strong) UIImage *disabledBackground;
@property(nonatomic) UITextFieldViewMode clearButtonMode; //显示[x]清除图标的时机
@property(nullable, nonatomic, strong) UIView *leftView;
@property(nonatomic) UITextFieldViewMode leftViewMode;
@property(nullable, nonatomic, strong) UIView *rightView;
@property(nonatomic) UITextFieldViewMode rightViewMode;
//字体大小自适应
@property(nonatomic) BOOL adjustsFontSizeToFitWidth;
@property(nonatomic) CGFloat minimumFontSize;
//编辑相关属性
@property(nonatomic, readonly, getter=isEditing) BOOL editing;
@property(nonatomic) BOOL clearsOnBeginEditing; //编辑文本前清空内容,相关委托方法可以覆盖该属性
@property(nonatomic) BOOL clearsOnInsertion;
@property(nonatomic) BOOL allowsEditingTextAttributes; //是否允许改变文本样式
//尺寸属性方法,获取不同子控件的尺寸
- (CGRect)textRectForBounds:(CGRect)bounds;
- (void)drawTextInRect:(CGRect)rect;
- (CGRect)placeholderRectForBounds:(CGRect)bounds;
- (void)drawPlaceholderInRect:(CGRect)rect;
- (CGRect)borderRectForBounds:(CGRect)bounds;
- (CGRect)editingRectForBounds:(CGRect)bounds;
- (CGRect)clearButtonRectForBounds:(CGRect)bounds;
- (CGRect)leftViewRectForBounds:(CGRect)bounds;
- (CGRect)rightViewRectForBounds:(CGRect)bounds;
//自定义样式,大多数时候没必要
@property(nullable, readwrite, strong) UIView *inputView;
@property(nullable, readwrite, strong) UIView *inputAccessoryView;
导航控制器,可以实现页面的管理
//初始化
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController;
- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass
toolbarClass:(Class)toolbarClass;
//委托,用于控制导航栏的生命周期和动画属性
@property(nullable, nonatomic, weak) id<UINavigationControllerDelegate> delegate;
//viewController控制
@property(nullable, nonatomic, readonly, strong) UIViewController *topViewController;
@property(nullable, nonatomic, readonly, strong) UIViewController *visibleViewController;
@property(nonatomic, copy) NSArray<__kindof UIViewController *> *viewControllers;//所有视图
- (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers
animated:(BOOL)animated; //替换视图
//页面跳转相关
- (void)pushViewController:(UIViewController *)viewController
animated:(BOOL)animated;
- (UIViewController *)popViewControllerAnimated:(BOOL)animated;
- (NSArray<__kindof UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated;
- (NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController
animated:(BOOL)animated;
@property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer;//弹出页面的手势
//顶部导航栏工具条操作
@property(nonatomic, readonly) UINavigationBar *navigationBar;//顶部导航栏,可以设置外观和控件
@property(nonatomic, readwrite, assign) BOOL hidesBarsOnTap;
@property(nonatomic, readwrite, assign) BOOL hidesBarsOnSwipe;
@property(nonatomic, readwrite, assign) BOOL hidesBarsWhenVerticallyCompact;
@property(nonatomic, readwrite, assign) BOOL hidesBarsWhenKeyboardAppears;
@property(nonatomic, getter=isNavigationBarHidden) BOOL navigationBarHidden;
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;
@property(nonatomic, readonly, assign) UITapGestureRecognizer *barHideOnTapGestureRecognizer;
@property(nonatomic, readonly, strong) UIPanGestureRecognizer *barHideOnSwipeGestureRecognizer;
标签控制器,可以实现页面管理
@property(nonatomic, readonly) UITabBar *tabBar; //底部的标签栏
@property(nullable, nonatomic, weak) id<UITabBarControllerDelegate> delegate;
//页面控制
@property(nullable, nonatomic, copy) NSArray<__kindof UIViewController *> *viewControllers;
- (void)setViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers
animated:(BOOL)animated;
//可以对VC进行重排序
@property(nullable, nonatomic, copy) NSArray<__kindof UIViewController *> *customizableViewControllers;
@property(nullable, nonatomic, assign) __kindof UIViewController *selectedViewController;
@property(nonatomic) NSUInteger selectedIndex;
UITabBarControllerDelegate
- (BOOL)tabBarController:(UITabBarController *)tabBarController
shouldSelectViewController:(UIViewController *)viewController;
- (void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController *)viewController;
传递链
由用户交互触发,由系统向离用户最近的view传递,目的是找出第一响应者(First Responder)。
UIApplication –> window –> root view –> … –> lowest view
流程描述:
1、 用户点击屏幕产生触摸事件
2、 系统将这个事件加入到一个由 UIApplication 管理的事件队列中
3、 UIApplication 会从消息队列里取事件分发下去,首先传给 UIWindow
4、 UIWindow 调用 hitTest:withEvent: 方法返回一个最终响应的视图
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
5、 如果最终的返回视图有值,那么这个视图就作为响应视图,结束整个事件传递;如果没有值,那么就会将 UIWindow 作为响应者。
响应链
系统找到第一响应者后,开始处理事件,从接收响应的 view 开始一级一级向上传递,直到事件被处理。
First Responder –> super view –> … –> view controller –> window –> Application –> AppDelegate
如果到最后都没有能够处理事件的组件,则丢弃这一事件。
OC的一个重要基类,是 UIApplication、UIViewController、UIView的父类,定义了各种用户交互相关的方法,是用户操作交互的直接对象。
//获取响应链上的下一个responder
//对于一个控件来说,这个属性意味着获取它的viewController或者superView,是一种不用设置代理访问controller的方法。
//这个方法可以重写,自定义返回的控件
@property(nonatomic, readonly, nullable) UIResponder *nextResponder;
//设置或撤销第一响应者的相关方法,主要用于输入框获取焦点
@property(nonatomic, readonly) BOOL isFirstResponder;
@property(nonatomic, readonly) BOOL canBecomeFirstResponder;
- (BOOL)becomeFirstResponder;
@property(nonatomic, readonly) BOOL canResignFirstResponder;
- (BOOL)resignFirstResponder;
//点击事件,直接重写相关方法即可,系统会自动调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;//点击事件意外取消的情况(如电话)
//晃动事件或者远程控制(线控等)事件
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
//按键事件
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event;
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event;
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event;
- (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event;
//键盘,当需要自定义键盘时重写这个view
@property(nullable, nonatomic, readonly, strong) __kindof UIView *inputView;
@property(nullable, nonatomic, readonly, strong) UIInputViewController *inputViewController;
//键盘顶上的小横条
@property(nullable, nonatomic, readonly, strong) __kindof UIView *inputAccessoryView;
@property(nullable, nonatomic, readonly, strong) UIInputViewController *inputAccessoryViewController;
- (void)reloadInputViews;
//键盘通知相关的常量,配合NotificationCenter使用
//键盘通知事件
const NSNotificationName UIKeyboardWillChangeFrameNotification;
const NSNotificationName UIKeyboardDidChangeFrameNotification;
const NSNotificationName UIKeyboardWillHideNotification;
const NSNotificationName UIKeyboardDidHideNotification;
const NSNotificationName UIKeyboardWillShowNotification;
const NSNotificationName UIKeyboardDidShowNotification;
//键盘事件通知信息dict的key
NSString *const UIKeyboardAnimationCurveUserInfoKey;
NSString *const UIKeyboardAnimationDurationUserInfoKey;
NSString *const UIKeyboardFrameBeginUserInfoKey;
NSString *const UIKeyboardFrameEndUserInfoKey;
NSString *const UIKeyboardIsLocalUserInfoKey;
当以下几种情况时,UIView不接受用户交互:
手势识别器,将一系列touches识别为一个手势,并触发相应操作。 这个类一般不直接使用,而是使用其子类:
UITapGestureRecognizer //点击,可以设置点击次数和触摸点数量
UIPinchGestureRecognizer //双指缩放手势,可设置比例和速度
UIRotationGestureRecognizer //双指旋转手势,可设置旋转的角度和速度
UISwipeGestureRecognizer //滑动手势,可设置滑动方向和触摸点数量
UILongPressGestureRecognizer //长按手势,可设置触摸点数量,触发前的点击次数、长按时间,允许手指移动的距离
UIPanGestureRecognzer //拖拽手势,可设置位置、触摸点数量、速度等
UIScreenEdgePanGestureRecognzer //在屏幕边缘的平移手势,可设置在哪个边缘
定义手势之后,需要调用相关 view的addGestureRecognizer 进行绑定,才能使手势识别生效。
UIGestureRecognizer拥有和UIResponder相同的点击事件与按键事件,见UIResponder类中的介绍。
@property(nullable, nonatomic, copy) NSString *name;//用于标识不同的手势识别器
//绑定方法
- (instancetype)initWithTarget:(id)target action:(SEL)action;
- (void)addTarget:(id)target action:(SEL)action;
- (void)removeTarget:(id)target action:(SEL)action;
//点击信息
- (CGPoint)locationInView:(UIView *)view;
- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(UIView *)view;
@property(nonatomic, readonly) NSUInteger numberOfTouches;
//手势信息
@property(nonatomic, readwrite) UIGestureRecognizerState state;
@property(nullable, nonatomic, readonly) UIView *view; //手势绑定的view
@property(nonatomic, getter=isEnabled) BOOL enabled; //是否启用
//手势识别结束时调用
- (void)reset;
//处理手势冲突的方法
//无视手势之外的点击
- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent *)event;
- (void)ignorePress:(UIPress *)button forEvent:(UIPressesEvent *)event;
//设置手势优先级
- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer;
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer;
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;//参数手势会取消调用者手势
//当识别到该手势时,会取消绑定的view上所有的点击。该属性默认为YES,可能会引发点击事件的冲突。
//如需要点击tableview空白区域触发事件,就应当将此属性设置为NO。
@property(nonatomic) BOOL cancelsTouchesInView;
UIGestureRecognizerDelegate
@property(nullable, nonatomic, weak) id<UIGestureRecognizerDelegate> delegate;
允许用户进行更细粒度的操作
//是否允许手势识别器进行识别对象
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceivePress:(UIPress *)press;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveEvent:(UIEvent *)event;
//多手势处理
//是否允许同时处理两个手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
//是否可以终止别的手势/被别的手势终止
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
UITouch
点击的位置、控件、次数、类型、手势、事件、尺寸、移动、力度、相位(点击开始、结束等不同阶段)等信息。
UIPress
press事件的信息,同上。
UIEvent
用户交互事件,存放事件类型、交互的窗口和控件、时间戳、触摸点的信息等。
//触摸点信息
@property(nonatomic, readonly, nullable) NSSet<UITouch *> *allTouches;
- (NSSet<UITouch *> *)touchesForView:(UIView *)view;
- (NSSet<UITouch *> *)touchesForWindow:(UIWindow *)window;
- (NSArray<UITouch *> *)coalescedTouchesForTouch:(UITouch *)touch;//按顺序获取触摸点,以实现顺畅的连线
- (NSArray<UITouch *> *)predictedTouchesForTouch:(UITouch *)touch;
- (NSSet<UITouch *> *)touchesForGestureRecognizer:(UIGestureRecognizer *)gesture;
//子类
@interface UIPressesEvent : UIEvent
评论区