UI进阶

作者: 恒筠 | 来源:发表于2018-03-07 16:10 被阅读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

    • 在程序当中,状态栏和键盘,它都属性是 个窗 .可以通过打印的 式来验证. 设置window的层级.UIWindowLevelNormal它是 个CGFloat类型. self.window.windowLevel = UIWindowLevelNormal UIWindowLevelNormal < UIWindowLevelStatusBar < UIWindowLevelAlert

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

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

    相关文章

      网友评论

          本文标题:UI进阶

          本文链接:https://www.haomeiwen.com/subject/zwnjfftx.html