UI进阶

2018-03-07  本文已影响0人  恒筠

第一课

1UIApplication

15121246699537.jpg

2.PCH的配置

15121249209730.jpg

3.注册推送

以下分别是 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

5.从Storyboard加载控制器

15123761360920.jpg

第二课

15124028675903.jpg
15124028927003.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.事件传递

模拟系统的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的基本操作

        _imageView.layer.cornerRadius = 50;
        裁剪,超出裁剪区域的部分全部裁剪掉
        _imageView.layer.masksToBounds = YES;
        注意:UIImageView当中Image并不是直接添加在层上面的.这是添加在layer当中的contents里.
        我们设置层的所有属性它只作用在层上面.对contents里面的东西并不起作用.所以我们看不到图片有圆角的效果.
        想要让图片有圆角的效果.可以把masksToBounds这个属性设为YES,
        当设为YES,把就会把超过根层以外的东西都给裁剪掉.
 只有旋转的时候才可以看出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.jpg

1.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.什么场景使用核心动画最多?
  在转场动画中,核心动画的类型比较多
  根据一个路径做动画,只能用核心动画(帧动画)
  动画组:同时做多个动画
上一篇下一篇

猜你喜欢

热点阅读