iOS基础之UIView、CALayer、UIControl、U
2019-06-25 本文已影响0人
平安喜乐698
目录
1. UIView : UIResponder
2. CALayer : NSObject
3. UIControl : UIView
4. UIResponder : NSObject 事件响应基类
5. UIWindow : UIView
6. UIApplication : UIResponder
7. UIScreen : NSObject
8. UIDevice : NSObject
1. UIView : UIResponder
几乎所有控件都继承UIView(即都拥有UIView的属性和方法)
父视图先于子视图渲染;
子视图在父视图上方;
子视图只有一个父视图,父视图可有多个子视图;
默认子视图的绘制范围可超出父视图;
视图后者居上;
UIView *view=[UIView new];
[self.view addSubview:view];
[view autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero];
常用
// 设置 frame
[view setFrame:CGRectMake(0, 0, 0, 0)];
// 设置 背景色
[view setBackgroundColor:[UIColor blueColor]];
// 设置 透明度
[view setAlpha:1.0];
// 设置 是否隐藏
[view setHidden:true];
// 设置 是否剪裁(true则子视图不会超过父视图的范围)
[view setClipsToBounds:true];
// 设置 tag(用于获取指定控件)
[view setTag:100];
// 获取 指定View(根据tag,不止可以从父视图中获取,还可以是从父父...View中获取,注意tag冲突)
UIView *cusView=[self.view viewWithTag:100];
子视图(添加/移除)
// 获取所有一级子视图
NSArray *viewArr=[view subviews];
// 获取所在index
NSInteger index=[view.subviews indexOfObject:subView];
// 移到最上
[view bringSubviewToFront:subView];
// 移到最下
[view sendSubviewToBack:subView];
// 交换视图(指定索引)
[view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
// 判断view 是否是 view2或View2的子View(包含孙子辈)
BOOL isSubsView=[view isDescendantOfView:view2];
// 添加子视图
[view addSubview:subView];
// 插入子视图(0在最下边,超过最大值则相当于addSubView不会崩)
[view insertSubview:subView atIndex:0];
// 插入子视图(位于指定视图上方)
[view insertSubview:subView aboveSubview:subView2];
// 插入子视图(位于指定视图下方)
[view insertSubview:subView belowSubview:subView2];
// 从父视图中移除
[subView removeFromSuperview];
// 移除所有子视图
[view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
圆角、阴影、边框线(更多layer操作参见CALayer)
2. CALayer
1、一个UIView对应一个CALayer(创建View后自动创建layer,真正用来显示内容,可以独立显示)。改变view的位置大小实质:改变layer的位置大小。若superView和view构成父子视图,则superView.layer和view.layer构成父子图层关系
2、CALayer不能响应交互(不是NSResponder的子类),UIView(是对CALayer的封装)可以响应交互。有些操作必须使用CALayer(如:阴影、圆角、边框线、3D形变、图像绘制、复杂动画)。
常用操作
圆角、阴影、边框线
// 设置 圆角(对子图层无效)
[view.layer setCornerRadius:5.0];
// 设置 是否剪裁
[view.layer setMasksToBounds:true];
// 阴影
// 需要设置view的背景色,否则会失效。剪裁会导致阴影被剪裁掉。
// 阴影是根据contents内容(没有则是图层边界)绘制
// 设置 阴影色
[view.layer setShadowColor:[UIColor blueColor].CGColor];
// 设置 阴影不透明度(默认0)
[view.layer setShadowOpacity:1];
// 设置 阴影偏移(横向,纵向),默认(0,-3)阴影在上
[view.layer setShadowOffset:CGSizeMake(0, 0)];
// 设置 阴影模糊度(0时边界明显)
[view.layer setShadowRadius:10];
// 边框线 颜色
[view.layer setBorderColor:[UIColor whiteColor].CGColor];
// 边框线 宽度(默认0)
[view.layer setBorderWidth:1.0];
// 透明度(默认1) ==UIView的alpha ,影响子层级
layer1.opacity=1;
// 隐藏
layer1.hidden=true;
// 即 View的center(0.5*width,0.5*height)
layer1.position;
// 通过bounds center transform来确定
// 注意:当旋转后,值等于把旋转后的VIew全部罩住的虚拟矩形的frame
layer1.frame;
// (0,0,原width,原height)
layer1.bounds;
// z坐标轴的位置,图层的显示顺序(别太小浮点计算耗时)
// 只能影响显示的层次,不能改变事件传递的顺序
layer1.zPosition=1.0;
// bgColor
layer1.backgroundColor=[UIColor blueColor].CGColor;
// 添加删除layer
[view.layer insertSublayer:layer1 above:layer2];
[view.layer insertSublayer:layer1 below:layer2];
[view.layer insertSublayer:layer1 atIndex:0];
[view.layer addSublayer:layer1];
[layer1 removeFromSuperlayer];
// 子layer数组
NSArray<CALayer *> *subArray=view.layer.sublayers;
// 父layer
CALayer *superLayer=view.layer.superlayer;
// 返回点击中的layer
CALayer *layer=[layer1 hitTest:CGPointMake(100, 100)];
// 锚点,默认:(0.5,0.5),可用作旋转时的中心点
layer1.anchorPoint=CGPointMake(0.1, 0.1);
// 是否包含此点(通过坐标转换而来的point)
[layer1 containsPoint:CGPointZero];
// 是否双面绘制(默认:true)(反转180之后的背面)
layer1.doubleSided=false;
// 将图层和子图层整合成一张图绘制
layer1.shouldRasterize=true;
// 拉伸(前提shouldRasterize为true)
layer1.rasterizationScale=[UIScreen mainScreen].scale;
坐标转换
// 坐标转换 将一个点或rect 转换到另一个layer的坐标系下 from则点原是from中的
[layer1 convertRect:CGRectZero toLayer:layer2];
[layer1 convertRect:CGRectZero fromLayer:layer2];
[layer1 convertPoint:CGPointZero toLayer:layer2];
[layer1 convertPoint:CGPointZero fromLayer:layer2];
contents
// 设置contents为图片
[view.layer setContents:[UIImage imageNamed:@"a"].CGImage];
// img填充格式 (左右正常,上下怪)
[view.layer setContentsGravity:kCAGravityResize];
/*
kCAGravityResizeAspectFill(变换size宽高比例填充,可能超出layer)、kCAGravityResize(变换size不按比例填充,不会超出layer,其他都可能超出,默认)、
以下模式都会超出(变换size宽高比例填充,可能超出layer)
kCAGravityTop(底部对齐)、kCAGravityBottom(顶部对齐)、kCAGravityLeft(左边对齐)、kCAGravityRight(右边对齐)、kCAGravityCenter(中心点对齐)、kCAGravityTopLeft(左下角对齐)、kCAGravityBottomLeft(左上角对齐)、kCAGravityTopRight(右下角对齐)、kCAGravityBottomRight(右上角对齐)
*/
// 默认:1正常屏幕(2则每点2像素,若设置了contentsGravity则无效)
[view.layer setContentsScale:2];
// 显示裁剪图片: 0~1(此处显示图片左上角)
view.layer.contentsRect=CGRectMake(0, 0, 0.5, 0.5);
// 显示拉伸压缩图片 可以将圆形拉伸为圆角矩形(0.5,0.5,0,0)
view.layer.contentsCenter=CGRectMake(0.5,0.5,0.5,0.5);
- layer使用示例
预期效果图(内凹陷+圆角+阴影):

部分代码如下:
// 添加背景layer
CAShapeLayer *bgLayer = [CAShapeLayer layer];
[bgLayer setFillColor:[UIColor whiteColor].CGColor];
// 设置阴影...
[bgLayer setPath:({
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, 10)];
[path addArcWithCenter:CGPointMake(10, 10) radius:10 startAngle:M_PI endAngle:M_PI*1.5 clockwise:true]; // 左上角
// path....
path.CGPath;
})];
//
[contentView.layer insertSublayer:bgLayer atIndex:0];
3. UIControl : UIView
很多可交互的控件都继承了UIControl(即拥有它的属性和方法)
UIControl的属性
enable 控件是否禁用
selected 控件是否被选中
highlighted 控件是否高亮
contentVerticalAlignment 控件内容 垂直方向对齐方式
UIControlContentVerticalAlignmentCenter
UIControlContentVerticalAlignmentTop
UIControlContentVerticalAlignmentBottom
UIControlContentVerticalAlignmentFill
contentHorizontalAlignment 控件内容 水平方向对齐方式
UIControlContentHorizontalAlignmentCenter
UIControlContentHorizontalAlignmentLeft
UIControlContentHorizontalAlignmentRight
UIControlContentHorizontalAlignmentFill
state state(readOnly)
UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected
UIControlStateFocused
UIControlStateApplication
UIControlStateReserved
UIControl的方法
// 添加/移除 事件监听
- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
- (void)removeTarget:(nullable id)target action:(nullable SEL)action forControlEvents:(UIControlEvents)controlEvents;
controlEvents(控件主要响应的3种事件):
1.基于触摸的事件
UIControlEventTouchDown 触摸事件(单点)
UIControlEventTouchDownRepeat 触摸事件(多点)
UIControlEventTouchDragInside 在控件内拖动
UIControlEventTouchDragOutside 在控件外拖动
UIControlEventTouchDragEnter 由控件外到控件内拖动
UIControlEventTouchDragExit 由控件内到控件外拖动
UIControlEventTouchUpInside 点击事件
UIControlEventTouchUpOutside 件外抬起
UIControlEventTouchCancel 取消触摸事件
2.基于值改变的事件
UIControlEventValueChanged 值改变事件
3.基于编辑的事件
UIControlEventEditingDidBegin 开始编辑事件
UIControlEventEditingChanged 文本内容改变事件
UIControlEventEditingDidEnd 编辑结束事件
UIControlEventEditingDidOnExit 退出编辑事件
所有事件
UIControlEventAlltouchEvents 所有触摸事件
UIControlEventAllEditingEvents 所有编辑事件
UIControlEventAllEvents 所有事件
4. UIResponder : NSObject 事件响应基类
UIView、UIViewController、UIWindow、UIApplication、AppDelegate均继承自UIResponder
// 是否 可以成为/注销第一响应者
[responder canBecomeFirstResponder];
[responder canResignFirstResponder];
// 是否 是第一响应者
[responder isFirstResponder];
// 成为/注销 第一响应者(常用于使UITextField获取/失去焦点)
[responder becomeFirstResponder];
[responder resignFirstResponder];
// 响应者链中的下一个响应者
UIResponder *nextResponder=[responder nextResponder];
以下方法(可用在子类中覆写)
触摸
// 开始触摸
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{}
// 触摸后移动
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{}
// 触摸取消
-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{}
// 触摸结束
-(void)touchesEnded:(NSSet<UITouch *> *)touches 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{}
移动
// 开始移动
-(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{}
// 结束移动
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{}
// 取消移动
-(void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event{}
5. UIWindow : UIView
UIWindow属性和方法
// 屏幕。默认是[UIScreen mainScreen],改变会耗内存。
@property(nonatomic,strong) UIScreen *screen;
// 显示优先级(默认为0,大在上,相同也在上)
// UIWindowLevelNormal 0、UIWindowLevelAlert 2000、UIWindowLevelStatusBar 1000、自定义数字
@property(nonatomic) UIWindowLevel windowLevel;
// 主控制器。改变可以更换根界面。
@property(nullable, nonatomic,strong) UIViewController *rootViewController;
// window是否是keyWindow
@property(nonatomic,readonly,getter=isKeyWindow) BOOL keyWindow;
// 使window变为keyWindow
[window makeKeyWindow];
// 使主窗口可见
// 不同于View(会添加到其他View上),Window创建后使用 [myWindow makeKeyAndVisible];
[self.window makeKeyAndVisible];
// 可查看当前所有windows
[UIApplication sharedApplication].windows
// 分发事件
[window sendEvent:[UIEvent new]];
// window间坐标转换
CGRect rect=[window convertRect:CGRectMake(0, 0, 0, 0) toWindow:window2];
CGPoint point=[window convertPoint:CGPointMake(0, 0) toWindow:window2];
CGRect rect=[window convertRect:CGRectMake(0, 0, 0, 0) fromWindow:window2];
CGPoint point=[window convertPoint:CGPointMake(0, 0) fromWindow:window2];
// 子类覆写,不能直接调用
- (void)becomeKeyWindow;
- (void)resignKeyWindow;
常用(弹窗)
// 主窗口添加子视图,不建议直接加到keyWindow上,级别太高
[[UIApplication sharedApplication].keyWindow addSubview:[UIView new]];
通知
UIWindowDidBecomeVisibleNotification // window可见
UIWindowDidBecomeHiddenNotification // window隐藏
UIWindowDidBecomeKeyNotification // makekey后
UIWindowDidResignKeyNotification // resignKey后
didFinishLaunchingWithOptions
// 应用加载完毕后调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 设置 主窗口
self.window=[[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
// 设置 主窗口背景色
[self.window setBackgroundColor:[UIColor whiteColor]];
// 设置 主窗口可见(必须调用)
[self.window makeKeyAndVisible];
// 设置 主窗口根控制器(常用于切换两端)
[self.window setRootViewController:[[YTNavController alloc]initWithRootViewController:[YTVoiceViewController new]]];
// 初始化一些第三方
[self setupThird];
return YES;
}
6. UIApplication : UIResponder
一个应用对应一个UIApplication
// 获取 UIApplication(当前应用的单例)
UIApplication *sharedApplication=[UIApplication sharedApplication];
// 获取 UIWindow(主窗口,一般情况下:应用只有一个主窗口)
UIWindow *window=sharedApplication.keyWindow;
// 获取 AppDelegate
id<UIApplicationDelegate> dele=sharedApplication.delegate;
// 应用角标
[sharedApplication setApplicationIconBadgeNumber:-1]; // -1角标清0
// 获取 应用当前状态
UIApplicationState state=sharedApplication.applicationState;
/*
UIApplicationStateActive, 活跃状态(可交互)
UIApplicationStateInactive,
UIApplicationStateBackground 后台
*/
// 获取 应用后台存活时间(只读)
NSTimeInterval backTime=sharedApplication.backgroundTimeRemaining;
// 获取 应用后台刷新状态
UIBackgroundRefreshStatus status=sharedApplication.backgroundRefreshStatus;
/*
UIBackgroundRefreshStatusRestricted, //
UIBackgroundRefreshStatusDenied, // 不允许刷新
UIBackgroundRefreshStatusAvailable // 允许刷新
*/
// 忽略交互事件
[sharedApplication beginIgnoringInteractionEvents];
// 接受交互事件
[sharedApplication endIgnoringInteractionEvents];
跳转(具体参考iOS之跳转)
// 是否允许打开其他应用
BOOL isCanOpen=[sharedApplication canOpenURL:[NSURL URLWithString:@""]];
// 打开其他应用
[sharedApplication openURL:[NSURL URLWithString:@""]];
[sharedApplication openURL:[NSURL URLWithString:@""] options:@{} completionHandler:^(BOOL success) {
}];
状态栏
状态栏字体颜色(默认:黑色) ,两种:
黑色(UIStatusBarStyleDefault,默认),状态栏字体白色
白色(UIStatusBarStyleLightContent),状态栏字体黑色。
改为白色:
方法一(此方式已过期) info.plist
View controller-based status bar appearance :false // 默认为true
status bar style :UIStatusBarStyleLightContent // 默认为UIStatusBarStyleDefault
注意:
1. true 则 [UIApplication sharedApplication].statusBarStyle 无效(preferredStatusBarStyle方法有效,若需要设置个别页的状态栏颜色,则在willAppear willDisAppear中调用即可)
2. false 则 仅[UIApplication sharedApplication].statusBarStyle 设置有效(preferredStatusBarStyle方法无效)
方法二 preferredStatusBarStyle方法(前提:上述plist使用默认true)
// 状态栏(如果VC在navC中,则需在navC中添加该方法,否则无效)
// VC中
- (UIStatusBarStyle)preferredStatusBarStyle{
// 状态栏为白色. UIStatusBarStyleDefault:黑色
return UIStatusBarStyleLightContent;
}
// navC中
- (UIStatusBarStyle)preferredStatusBarStyle{
return [self.topViewController preferredStatusBarStyle];
}
注意:
// 以下方法会强制调用navC(没有navC 则VC)中的preferredStatusBarStyle。
[self setNeedsStatusBarAppearanceUpdate];
// 获取 应用状态栏方向(readOnly)
UIInterfaceOrientation interfaceOrien=sharedApplication.statusBarOrientation;
/*
UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait, Home在下
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown, Home在上
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight, Home在
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
*/
// 获取 应用状态栏动画时间(readOnly)
NSTimeInterval durTime=sharedApplication.statusBarOrientationAnimationDuration;
// 获取 应用状态栏frame(readOnly)
CGRect applicationFrame=sharedApplication.statusBarFrame;
// 设置 是否显示网络加载圈(状态栏中)
[sharedApplication setNetworkActivityIndicatorVisible:true];
// 隐藏状态栏(此方式已过期)
sharedApplication.statusBarHidden=true;
[sharedApplication setStatusBarHidden:true withAnimation:UIStatusBarAnimationFade];
通知
应用进入后台后
UIApplicationDidEnterBackgroundNotification
应用即将进入前台时
UIApplicationWillEnterForegroundNotification
应用加载完毕后
UIApplicationDidFinishLaunchingNotification
应用允许交互后
UIApplicationDidBecomeActiveNotification
应用即将不允许交互时
UIApplicationWillResignActiveNotification
应用收到内存紧张警告时
UIApplicationDidReceiveMemoryWarningNotification
应用即将销毁时
UIApplicationWillTerminateNotification;
应用后台刷新状态改变
UIApplicationBackgroundRefreshStatusDidChangeNotification
应用?
UIApplicationSignificantTimeChangeNotification;
应用状态栏方向即将改变时
UIApplicationWillChangeStatusBarOrientationNotification
应用状态栏方向改变后
UIApplicationDidChangeStatusBarOrientationNotification
应用状态栏即将改变frame
UIApplicationWillChangeStatusBarFrameNotification
应用状态栏改变frame后
UIApplicationDidChangeStatusBarFrameNotification
7. UIScreen : NSObject
// 获取 屏幕
UIScreen *mainScreen=[UIScreen mainScreen];
// 获取 屏幕大小
CGRect rect=mainScreen.bounds;
8. UIDevice : NSObject
// 获取 当前设备
UIDevice *currentDevice=[UIDevice currentDevice];
// 获取 设备昵称
NSString *deviceName=currentDevice.name;
// 获取 设备机型 (iPhone / iPod touch / iPad)
NSString *deviceModel=currentDevice.model;
// 获取 设备机型
NSString *deviceLModel=currentDevice.localizedModel;
// 获取 设备系统
NSString *deviceSysName=currentDevice.systemName;
// 获取 设备系统版本
NSString *deviceSysVersion=currentDevice.systemVersion;
// 获取 设备方向
UIDeviceOrientation deviceOrientation=currentDevice.orientation;
/*
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait, // Home键在下
UIDeviceOrientationPortraitUpsideDown, // Home键在上
UIDeviceOrientationLandscapeLeft, // Home键在左
UIDeviceOrientationLandscapeRight, // Home键在右
UIDeviceOrientationFaceUp, // 水平放置,正面朝上
UIDeviceOrientationFaceDown // 水平放置,正面朝下
*/
电池
// 是否监测电池
BOOL battoryMonitor=currentDevice.batteryMonitoringEnabled;
// 获取电池电量
float deviceBattoryLevel=currentDevice.batteryLevel;
// 获取电池状态
UIDeviceBatteryState state=currentDevice.batteryState;
/*
UIDeviceBatteryStateUnknown,
UIDeviceBatteryStateUnplugged, // 耗电中
UIDeviceBatteryStateCharging, // 充电中 小于100%
UIDeviceBatteryStateFull, // 充电中 等于100%
*/
旋转
// 获取 设备旋转时是否发送通知
BOOL isRoteNoti=currentDevice.generatesDeviceOrientationNotifications;
// 允许设备旋转时发送通知
[currentDevice beginGeneratingDeviceOrientationNotifications];
// 不允许设备旋转时发送通知
[currentDevice endGeneratingDeviceOrientationNotifications];
UIUserInterfaceIdiom interFace=currentDevice.userInterfaceIdiom;
近距离
// 获取 设备近距离靠近时是否发送通知(例:用于通话时,放在耳朵旁界面变暗)
BOOL isProximityMonitor=currentDevice.proximityMonitoringEnabled;
// 获取 是否近距离靠近
BOOL isPro=currentDevice.proximityState;