UI进阶
第一课
1UIApplication
15121246699537.jpg2.PCH的配置
15121249209730.jpg3.注册推送
以下分别是 iOS 10 之前和之后的注册方式,其中的 UNAuthorizationOptions 里还可以找到 1 个 UNAuthorizationOptionCarPlay 的值是专为车载系统定制的值。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//iOS 10 before
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
//iOS 10
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!error) {
NSLog(@"request authorization succeeded!");
}
}];
return YES;
}
作者:pikacode
链接:http://www.jianshu.com/p/2f3202b5e758
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
4.UIWindows
- 在程序当中,状态栏和键盘,它都属性是 个窗 .可以通过打印的 式来验证. 设置window的层级.UIWindowLevelNormal它是 个CGFloat类型. self.window.windowLevel = UIWindowLevelNormal UIWindowLevelNormal < UIWindowLevelStatusBar < UIWindowLevelAlert
5.从Storyboard加载控制器
15123761360920.jpg第二课
15124028675903.jpg15124028927003.jpg
第三课
1.segue的底层实现
![15124762493040.jpg](https://img.haomeiwen.com/i10921965/1744fef944a93417.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)2.通知
当控制器销毁是记得移除通知
第四课
1.个人详情页代码
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
//NSLog(@"%@",NSStringFromCGRect(self.tableView.frame));
//1.凡是在导航条下面的scrollView.默认会设置偏移量.UIEdgeInsetsMake(64, 0, 0, 0)
//self.tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
//不要自动设置偏移量
self.automaticallyAdjustsScrollViewInsets = NO;
//让导航条隐藏
//self.navigationController.navigationBar.hidden = YES;
//导航条或者是导航条上的控件设置透明度是没有效果.
//self.navigationController.navigationBar.alpha = 0;
//设置导航条背景(必须得要使用默认的模式UIBarMetricsDefault)
//当背景图片设置为Nil,系统会自动生成一张半透明的图片,设置为导航条背景
[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
//当调用contentInset会自动调用scrollViewDidScroll
self.tableView.contentInset = UIEdgeInsetsMake(244, 0, 0, 0);
//设置标题
UILabel *title = [[UILabel alloc] init];
title.text = @"个人详情页";
[title sizeToFit];
title.textColor = [UIColor colorWithWhite:0 alpha:0];
self.navigationItem.titleView = title;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
//求偏移量
//当前点 - 最原始的点
NSLog(@"%f",scrollView.contentOffset.y);
CGFloat offset = scrollView.contentOffset.y - oriOfftY;
NSLog(@"offset======%f",offset);
CGFloat h = oriHeight - offset;
if (h < 64) {
h = 64;
}
self.heightConstr.constant = h;
//根据透明度来生成图片
//找最大值/
CGFloat alpha = offset * 1 / 136.0;
if (alpha >= 1) {
alpha = 0.99;
}
//拿到标题
UILabel *titleL = (UILabel *)self.navigationItem.titleView;
titleL.textColor = [UIColor colorWithWhite:0 alpha:alpha];
//把颜色生成图片
UIColor *alphaColor = [UIColor colorWithWhite:1 alpha:alpha];
//把颜色生成图片
UIImage *alphaImage = [UIImage imageWithColor:alphaColor];
//修改导航条背景图片
[self.navigationController.navigationBar setBackgroundImage:alphaImage forBarMetrics:UIBarMetricsDefault];
}
2.归档
15126589415829.jpg 15126589471912.jpg第五课
1.事件传递
- 1.当一个控件如果它的父控件不能够接收事件,那么它里面子控件也是不能接收事件的
- 2.当一个控件隐藏的时候,它里面的子控件也跟着隐藏
- 3.当一个控件透明的时候,它里面的子控件也跟着透明
模拟系统的hitText方法
//作用:去寻找最适合的View
//什么时候调用:当一个事件传递给当前View,就会调用.
//返回值:返回的是谁,谁就是最适合的View(就会调用最适合的View的touch方法)
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
//1.判断自己能否接收事件
if(self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) {
return nil;
}
//2.判断当前点在不在当前View.
if (![self pointInside:point withEvent:event]) {
return nil;
}
//3.从后往前遍历自己的子控件.让子控件重复前两步操作,(把事件传递给,让子控件调用hitTest)
int count = (int)self.subviews.count;
for (int i = count - 1; i >= 0; i--) {
//取出每一个子控件
UIView *chileV = self.subviews[i];
//把当前的点转换成子控件从标系上的点.
CGPoint childP = [self convertPoint:point toView:chileV];
UIView *fitView = [chileV hitTest:childP withEvent:event];
//判断有没有找到最适合的View
if(fitView){
return fitView;
}
}
//4.没有找到比它自己更适合的View.那么它自己就是最适合的View
return self;
}
//作用:判断当前点在不在它调用View,(谁调用pointInside,这个View就是谁)
//什么时候调用:它是在hitTest方法当中调用的.
//注意:point点必须得要跟它方法调用者在同一个坐标系里面
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
NSLog(@"%s",__func__);
return YES;
}
15128269778909.jpg
![[图片上传中...(15129827603014.jpg-7d8817-1520410012340-0)]
](https://img.haomeiwen.com/i10921965/89b8d5168b2a4d00.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2.抽屉效果
15129827509277.jpg 15129827603014.jpg第六课
1.定时器
1. 先要了解setNeedsDisplay
setNeedsDisplay底层会调 DrawRect 法重绘. 但是它不是 就进 重绘.它仅仅是设置了 个重绘标志,等到下 次屏幕刷新的时候才会 调 DrawRect 法.
如果使 NSTime的话,假设是0.01调 次重绘.假设屏幕0.02秒的时候它才刷新 次. 中间就会等0.01秒.
也就是每次都会等0.01秒这样累加上去.让变的越来越卡顿.
使 CADisplayLink时,它的定时器 法就是屏幕每次刷新的时候就会调 (通常屏幕 秒 钟刷新60次) 它和setNeedsDisplay调 DrawRect 法的时机正好吻合,不会出间等待间隔.不会出现 屏幕卡顿现象.
2.2如何使 CADisplayLink添加定时器?
Target:哪个对象要监听 法.
selector:监听的 法名称.
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)]; 想要让CADisplayLink 作,必须得要把它添加到主运 循环. 只要添加到主运 循环, 跟模式没有关系
[link addToRunLoop:[NSRunLoop mainRunLoop]
forMode:NSDefaultRunLoopMode];
2.NSAttributedString描述
字符属性
字符属性可以应用于 attributed string 的文本中。
NSString *const NSFontAttributeName;(字体)
NSString *const NSParagraphStyleAttributeName;(段落)
NSString *const NSForegroundColorAttributeName;(字体颜色)
NSString *const NSBackgroundColorAttributeName;(字体背景色)
NSString *const NSLigatureAttributeName;(连字符)
NSString *const NSKernAttributeName;(字间距)
NSString *const NSStrikethroughStyleAttributeName;(删除线)
NSString *const NSUnderlineStyleAttributeName;(下划线)
NSString *const NSStrokeColorAttributeName;(边线颜色)
NSString *const NSStrokeWidthAttributeName;(边线宽度)
NSString *const NSShadowAttributeName;(阴影)(横竖排版)
NSString *const NSVerticalGlyphFormAttributeName;
常量
1> NSFontAttributeName(字体)
该属性所对应的值是一个 UIFont 对象。该属性用于改变一段文本的字体。如果不指定该属性,则默认为12-point Helvetica(Neue)。
2> NSParagraphStyleAttributeName(段落)
该属性所对应的值是一个 NSParagraphStyle 对象。该属性在一段文本上应用多个属性。如果不指定该属性,则默认为 NSParagraphStyle 的defaultParagraphStyle 方法返回的默认段落属性。
3> NSForegroundColorAttributeName(字体颜色)
该属性所对应的值是一个 UIColor 对象。该属性用于指定一段文本的字体颜色。如果不指定该属性,则默认为黑色。
4> NSBackgroundColorAttributeName(字体背景色)
该属性所对应的值是一个 UIColor 对象。该属性用于指定一段文本的背景颜色。如果不指定该属性,则默认无背景色。
5> NSLigatureAttributeName(连字符)
该属性所对应的值是一个 NSNumber 对象(整数)。连体字符是指某些连在一起的字符,它们采用单个的图元符号。0 表示没有连体字符。1 表示使用默认的连体字符。2表示使用所有连体符号。默认值为 1(注意,iOS 不支持值为 2)。
6> NSKernAttributeName(字间距)
该属性所对应的值是一个 NSNumber 对象(整数)。字母紧排指定了用于调整字距的像素点数。字母紧排的效果依赖于字体。值为 0 表示不使用字母紧排。默认值为0。
7> NSStrikethroughStyleAttributeName(删除线)
该属性所对应的值是一个 NSNumber 对象(整数)。该值指定是否在文字上加上删除线,该值参考“Underline Style Attributes”。默认值是NSUnderlineStyleNone。
8> NSUnderlineStyleAttributeName(下划线)
该属性所对应的值是一个 NSNumber 对象(整数)。该值指定是否在文字上加上下划线,该值参考“Underline Style Attributes”。默认值是NSUnderlineStyleNone。
9> NSStrokeColorAttributeName(边线颜色)
该属性所对应的值是一个 UIColor 对象。如果该属性不指定(默认),则等同于 NSForegroundColorAttributeName。否则,指定为删除线或下划线颜色。更多细节见“Drawing attributedstrings that are both filled and stroked”。
10> NSStrokeWidthAttributeName(边线宽度)
该属性所对应的值是一个 NSNumber 对象(小数)。该值改变描边宽度(相对于字体size 的百分比)。默认为 0,即不改变。正数只改变描边宽度。负数同时改变文字的描边和填充宽度。例如,对于常见的空心字,这个值通常为3.0。
11> NSShadowAttributeName(阴影)
该属性所对应的值是一个 NSShadow 对象。默认为 nil。
12> NSVerticalGlyphFormAttributeName(横竖排版)
该属性所对应的值是一个 NSNumber 对象(整数)。0 表示横排文本。1 表示竖排文本。在 iOS 中,总是使用横排文本,0 以外的值都未定义。
第八课
1.CALayer的基本操作
- 设置阴影
- 默认图层是有阴影的, 只不过,是透明的
_RedView.layer.shadowOpacity = 1;
- 默认图层是有阴影的, 只不过,是透明的
- 设置图片的圆角半径
_imageView.layer.cornerRadius = 50;
裁剪,超出裁剪区域的部分全部裁剪掉
_imageView.layer.masksToBounds = YES;
注意:UIImageView当中Image并不是直接添加在层上面的.这是添加在layer当中的contents里.
我们设置层的所有属性它只作用在层上面.对contents里面的东西并不起作用.所以我们看不到图片有圆角的效果.
想要让图片有圆角的效果.可以把masksToBounds这个属性设为YES,
当设为YES,把就会把超过根层以外的东西都给裁剪掉.
- layer的 CATransform3D属性.
只有旋转的时候才可以看出3D的效果.
旋转
x,y,z 分别代表x,y,z轴.
CATransform3DMakeRotation(M_PI, 1, 0, 0);
平移
CATransform3DMakeTranslation(x,y,z)
缩放
CATransform3DMakeScale(x,y,z);
可以通过KVC的方式进行设置属性.
但是CATransform3DMakeRotation它的值,是一个结构体, 所以要把结构转成对象.
NSValue *value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, 0, 0)];
[_imageView.layer setValue:value forKeyPath:@"transform.scale"];
可以通过KVC的方式进行设置属性.
但是CATransform3DMakeRotation它的值,是一个结构体, 所以要把结构转成对象.
NSValue *value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, 0, 0)];
[_imageView.layer setValue:value forKeyPath:@"transform.scale"];
2.关于CALayer的疑惑?
为什么要使用CGImageRef、CGColorRef?
为了保证可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef
UIView和CALayer都能够显示东西,该怎样选择?
对比CALayer,UIView多了一个事件处理的功能。也就是说,CALayer不能处理用户的触摸事件,而UIView可以
如果显示出来的东西需要跟用户进行交互的话,用UIView;
如果不需要跟用户进行交互,用UIView或者CALayer都可以
CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级
3.隐式动画
如何取消隐式动画?
首先要了解动画底层是怎么做的.动画的底层是包装成一个事务来进行的.
什么是事务?
很多操作绑定在一起,当这些操作执行完毕后,才去执行下一个操作.
开启事务
[CATransaction begin];
设置事务没有动画
[CATransaction setDisableActions:YES];
设置动画执行的时长
[CATransaction setAnimationDuration:2];
提交事务
[CATransaction commit];
核心动画
15132255337759.jpg1.CABasicAnimation基础核心动画
CABasicAnimation *anim =[CABasicAnimation animation];
设置缩放属性
anim.keyPath = @"transform.scale";
缩放到最小
anim.toValue = @0;
设置动画执行的次数
anim.repeatCount = MAXFLOAT;
设置动画执行的时长
anim.duration = 0.25;
设置动画自动反转(怎么去, 怎么回)
anim.autoreverses = YES;
添加动画
[self.heartView.layer addAnimation:anim forKey:nil];
2.图片抖动(帧动画)CAKeyframeAnimation
1.帧动画介绍:
CAKeyframeAnimation它可以在多个值之间进行动画.
设置多值之间的属性为:
后面是一个数组,就是要设置的多个值.
anim.values = @[];
它还可以根据一个路径做动画.
anim.path = 自己创建的路径.
2.图片抖动思路:
其实就是做一个左右旋转的动画.先让它往左边旋转-5,再往右边旋转5度,再从5度旋转到-5度.
就会有左右摇摆的效果了.
具体实现代码
创建帧动画
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
设置动画属性为旋转
anim.keyPath = @"transform.rotation";
设置属性值为多个属性
anim.values = @[@(angle2radio(-5)),@(angle2radio(5)),@(angle2radio(-5))];
设置动画执行次数
anim.repeatCount = MAXFLOAT;
添加动画
[_imageView.layer addAnimation:anim forKey:nil];
3.根据圆形的路径做移动的效果.
创建路径
UIBezierPath *path = [UIBezierPath
bezierPathWithOvalInRect:CGRectMake(50, 50, 100, 100)];
[path addLineToPoint:CGPointMake(200, 500)];
把路径设为动画的属性
anim.path = path.CGPath;
3.转场动画CATransition
09-转场动画
1.什么是转场动画?
就是从一个场景转换到另一个场景,像导航控制器的push效果,就是一个转场.
2.如何创建转场动画
创建转场动画
CATransition *anim = [CATransition animation];
设置转场类型
anim.type = @"cube";
anim.duration = 1;
设置转场的方向
anim.subtype = kCATransitionFromLeft;
设置动画的开始位置
anim.startProgress = 0.5;
设置动画的结束位置
anim.endProgress =0.8;
添加动画.了
[_imageV.layer addAnimation:anim forKey:nil];
要执行动画的代码称为转场代码.
转场动画要和转场代码写在同一个方法当中才有动画效果.
3.UIView进行转场动画
[UIView transitionWithView:self.imageV duration:1
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
转场代码
} completion:^(BOOL finished) {
动画执行完毕时调用.
}];
使用UIView转场的类型比较少.
4.动画组CAAnimationGroup
可以同时执行多个动画.
创建组动画
CAAnimationGroup *group = [CAAnimationGroup animation];
平移
CABasicAnimation *anim = [CABasicAnimation animation];
anim.keyPath = @"position.y";
anim.toValue = @400;
缩放
CABasicAnimation *scaleAnim = [CABasicAnimation animation];
scaleAnim.keyPath = @"transform.scale";
scaleAnim.toValue = @0.5;
设置动画组属性
group.animations = @[anim,scaleAnim];
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;
添加组动画
[self.redView.layer addAnimation:group forKey:nil];
使用动画组的好处,不需要每次都去添加动画,设置动画完成时的属性.
只需要把要执行的动画,添加到动画组的animations数组当中即可,
最后把组动画添加到层上面,就会自动执行数组当中的动画.
动画完成时设置的属性也只需要设置一次.
5.UIView与核心动画对比?
1.UIView和核心动画区别?
核心动画只能添加到CALayer
核心动画一切都是假象,并不会改变真实的值。
2.什么时候使用UIView的动画?
如果需要与用户交互就使用UIView的动画.
不需要与用户交互可以使用核心动画
3.什么场景使用核心动画最多?
在转场动画中,核心动画的类型比较多
根据一个路径做动画,只能用核心动画(帧动画)
动画组:同时做多个动画