美文网首页iOSiOS零碎知识iOS学习资料整理+学习方法
斯坦福大学iOS开发公开课总结(七) :自定义视图,手势识别,绘

斯坦福大学iOS开发公开课总结(七) :自定义视图,手势识别,绘

作者: J_Knight_ | 来源:发表于2016-07-06 08:34 被阅读1095次

    本节课介绍了UIView的一些知识,自定义UIView的方法以及手势识别。最后应用本节所讲的大部分知识点向我们演示了一个绘制纸牌的Demo。

    UIView


    关于UIView,你需要知道的零散知识

    • 视图是可以多层嵌套的。
    • 每个视图可以有多个子视图,但是只能有一个父视图。
    • 控制器的view属性指向自己的顶级视图。
    • 令视图透明会加大系统的开销。
    • 通过判断控制器view的self.view.window是否存在来判断控制器view是否被显示出来。

    UIView的一些属性和方法

    @property CGFloat contentScaleFactor; //返回每个点所有的像素数 :非retina为1,retina为2
    
    - (UIView *)superView; //指向自己的父视图
    - (NSArray *)subview; //自己的所有子视图的数组
    
    - (void)addSubview: (Uiview *)aView;// 发送给目标父视图,让其把aView作为自己的子视图
    - (void)removeFromSuperview;  //消息发送给要移除的vie
    

    View的初始化方法:

    - (void)awakeFromNib {[self setup];}  //通过故事版创建的View的初始化
    - (id)initWithFrame: (CGRect)aRect    //通过纯代码创建的View的初始化
    {
         self = [super initWithFrame:aRect];
         [self setup];
         return self;
    }
    
    - (void)setup {....};
    

    Custom View 自定义视图

    在iOS中,自定义是图的方法是创建一个UIView的子类并重写 - (void)drawInRect:(Rect)rect方法。

    注意:永远都不要自己调用这个方法,要交给系统负责!
    可以调用以下的方法,告诉系统这个视图要被重绘:

    - (void)setNeedsDisplay;
    - (void)setNeedsDisplayInRect: (CGRect)aRect  
    

    那么具体怎样重写 - (void)drawInRect:(Rect)rect方法来绘图呢?
    答:应用Core Graphics的相关知识。

    Core Graphics

    Core Graphics是一套基于C的API框架,使用了Quartz作为绘图引擎,使用Core Graphics,可以创建直线、路径、渐变、文字与图像等内容,并可以做变形处理。

    Core Grephics的工作步骤:

    1. 取得图形上下文。
    2. 设置绘图路径(利用UIBezierPath)。
    3. 设置颜色。
    4. 用颜色填充路径 。

    各位看官不用着急,具体方法在最后的Demo代码里给大家呈现。

    UIGestureRecoginizer :手势识别抽象类


    简单介绍UIGestureRecoginizer是一个抽象类,它的各种子类可以用于识别各种不同的手势:如捏合,滑动等等。通过识别各种不同的手势,实现各种交互操作。

    使用步骤

    1. 在视图中添加手势识别对象。
    2. 提供手势发生时所需要调用的方法。

    手势种类:

    1. UIPanGestureRecognizer : 拖动手势

    - (void)setPannableView:(UIView*)pannableView
    {
         _pannableView = pananbleView;
         UIPanGestureRecognizer *pangr = [UIPanGestureRecognizer alloc] initWithTarget:pannableView action: @selector(pan:)];
         [pannableView addGestureRecognnizer:panr];
    } 
    

    2. UIPinchGestureReccognizer :捏合手势

    @property CGFloat scale;   捏合手势距离
    @property (readonly) CGFloat velocity; 每分钟变化的速度
    

    3. UIRotationGestureRecgnizer 旋转手势

    @property CGFloat rotation;   弧度
    @property (readonly) CGFloat velocity; 每秒变化的速度
    

    4. UISwipeGestureRecgnizer : 滑动手势

    @property UISwipeGestureRecognizerDirection direction 滑动方向
    @property NSUInteger numberOfTouchesRequired; 几只手指来完成
    

    5. UITapGestureRecognizer :点击手势

    @property NSUInteger numberOfTapsReqired;几次点击
    @property NSUInteger numberOfTouchesRequired;     几只手指来完成 
    

    以上第4,5项手势是非连续手势;1,2,3属于连续手势。
    注意区分滑动手势和拖动手势。滑动手势是指短促,快速地滑动的手势,而拖动手势是相对较慢,路径较长的手势。

    绘制纸牌Demo


    Demo需求

    • 绘制一张纸拍放到屏幕上,包括正面和背面。
    • 滑动手势可以翻牌。
    • 捏合手势可以伸缩纸牌正面的图案大小。

    Demo效果图

    左二图:翻牌 | 右二图:伸缩

    重要代码段

    1. 绘制纸牌正反面

    - (void)drawRect:(CGRect)rect {
    
        //初始化一个圆角矩形
        UIBezierPath *roundRect = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:[self cornerRadius]];
    
        //裁剪,保证不会绘制四角
        [roundRect addClip];
    
        //填充白色
        [[UIColor whiteColor] setFill];
         UIRectFill(self.bounds);
    
        //轮廓
        [[UIColor blackColor] setStroke];
        [roundRect stroke];
    
        if (self.faceUp) {
    
            //1. 纸牌正面
            //1.1 纸牌正面中间的图
            UIImage *faceImage = [UIImage imageNamed:[NSString stringWithFormat:@"%@%@",[self rankAsString],self.suit]];
    
            if (faceImage) {
    
                CGRect imageRect = CGRectInset(self.bounds, self.bounds.size.width * (1.0 - self.faceCardScaleFactor) + 20, self.bounds.size.height * ( 1.0 - self.faceCardScaleFactor  ) + 20);
                [faceImage drawInRect:imageRect];
            }
          
            //1.2 纸牌正面四个角
            [self drawCorners];
    
        }else{
    
            //2. 纸牌背面
            [[UIImage imageNamed:@"cardBack"] drawInRect:self.bounds];
        }
    }
    

    2. 绘制纸牌边角的花色和数字

    - (void)drawCorners
    {    
        //设定段落排列
        NSMutableParagraphStyle *paragraphStype = [[NSMutableParagraphStyle alloc] init];
        paragraphStype.alignment = NSTextAlignmentCenter;
    
       //设定字体
        UIFont *cornerFont = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
        cornerFont = [cornerFont fontWithSize:cornerFont.pointSize * [self cornerScaleFactor]]; 
    
        //角落文字
        NSAttributedString *cornerText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@", [self rankAsString], self.suit] attributes:@{NSFontAttributeName:cornerFont,NSParagraphStyleAttributeName:paragraphStype}];
    
        //左上角
        //1. 获得图片的rect
        CGRect textBounds;
        textBounds.origin = CGPointMake([self cornerOffset], [self cornerOffset]);
        textBounds.size = [cornerText size];
    
         //2.绘制文字
        [cornerText drawInRect:textBounds];
    
        //右下角
        //1. 获取上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
        // 2. 移动上下文
        CGContextTranslateCTM(context, self.bounds.size.width, self.bounds.size.height);
         //3. 翻转上下文(翻转180度)
        CGContextRotateCTM(context, M_PI);
         //4. 绘制
        [cornerText drawInRect:textBounds];
    }
    

    我们可以看到,图片和文字的绘图方法都是可以通过drawInRect:方法来进行:通过传入需要绘制的rect,可以让系统根据原始的素材(图片,文字)来绘图。

    3. 添加手势:连线方式

    /**
     *  滑动手势翻转牌
     *
     *  @param sender 滑动手势
     */
    
    - (IBAction)swipe:(id)sender {
     
       //翻转牌面
        self.playCardView.faceUp  = !self.playCardView.faceUp;
    
    }
    

    4. 添加手势:代码方式

    //1. 添加捏合手势
     [self.playCardView addGestureRecognizer:[[UIPinchGestureRecognizer alloc] initWithTarget:self.playCardView
                                                                                        action:@selector(pinch:)]];
    
    /**
     *  2. 捏合手势调用的方法
     *
     *  @param gesture 捏合手势
     */
    
    - (void)pinch:(UIPinchGestureRecognizer *)gesture
    {
        if (gesture.state == UIGestureRecognizerStateChanged || gesture.state == UIGestureRecognizerStateEnded) {
           //根据捏合的程度来伸缩图片
            self.faceCardScaleFactor *= gesture.scale;
            gesture.scale = 1.0;
    
        }
    }
    

    在手势识别调用的方法里,我们需要对手势本身的状态加以判断以确保各种交互的实现都是正确的。

    最后的话


    如果哪位小伙伴想拿到本文Demo的代码请不要客气,在评论里留言即可。
    而且十分欢迎给笔者的代码和文笔抛出宝贵的意见和建议~

    本文为笔者原创,如需转载,请事先与笔者交涉~

    2016.7.12日更新:


    笔者已经把目前为止整理的所有Demo(第二课到第十课)放入到了我的GitHub仓库里。分为英文注释版和中文注释版(英文注释要少一点,嘿嘿)想要的小伙伴可以果断下载~ 如果有不知道怎么下载的小伙伴请联系我~

    本文已在版权印备案,如需转载请访问版权印。48422928

    获取授权

    相关文章

      网友评论

      • a30e3ba2b372:楼主大神,可以求一份demo吗?1594297995@qq.com 谢谢啦
        a30e3ba2b372:@J_Knight 谢谢啦
        J_Knight_:@素肉丸子 https://github.com/knightsj/Stanford_iOS_Lecture_DemoBundle 这里都有哈~所有的
      • 挖牛速聘:感谢真神 382018398@qq.com
      • 会走路的键盘:zhangchangww@126.com 大神求发 :smiley:
        J_Knight_:@会走路的键盘 还没到大神的级别 :smile: 已发~
      • 拓跋鼠:你直接把代码放在链接里,不是省事很多嘛 还要一个个给别人发
        J_Knight_:@拓跋鼠 多谢建议~
        J_Knight_:@拓跋鼠 嗯 等我总结好10个之后就上github,现在还不够规模
      • devleoper_rui:大神 demo 呢 1067349543@q q.com
        J_Knight_:@瑞瑞瑞瑞瑞瑞 表叫我大神 :smile: 已发~
      • 路这么长:weekice.zh@gmail.com 楼主 求源码 谢谢了 :smile:
        J_Knight_:@路这么长 不客气~ 已发~
      • 垃圾___垃圾:直接上Github链接不就好了
        J_Knight_:@驿路梨花开 已经有仓库了https://github.com/Shijie0111/Stanford_iOS_Lecture_DemoBundle,目前只到第十课的Demo :smile: 感谢你的建议
        J_Knight_:@驿路梨花开 嗯嗯 大概等我整理到第十课的时候吧,还不够规模
      • 好看的昵称:楼主,求源码,谢谢,yauwaikong@163.com
        J_Knight_:@好看的昵称 已发~
      • a0b6e2a49203:yipiao773@126.com Thanks!^-^
        J_Knight_:@yipiao773 已发~
      • 桐丘:楼主,求源码,谢谢,wangchunping_2011@yahoo.com
        桐丘:@Hero_SJ 谢谢
        J_Knight_:@桐丘 已发~
      • 奔驰小跑:求demo,谢谢
        J_Knight_:@奔驰小跑 已发~
        奔驰小跑:@奔驰小跑 :smiley: 393864523@qq.com
      • ae12:讲的真心很好,请问斯坦福大学的这个公开课在哪里可以看到?
        J_Knight_:@Liqing_1938 谢谢啊~ 网易公开课呢http://open.163.com/movie/2014/1/M/7/M9H7S9F1H_M9H7TMJM7.html
      • 你好自己:大神 求demo
        J_Knight_:@月下恋芳 已发~
        你好自己:xulianpengXLP@126.com
      • overla5:m18855458786@163.com。谢谢
        overla5:@Hero_SJ 三克哟~
        J_Knight_:@失格人间 已发~
      • 谁是我我我:大神,求demo。祝你生活愉快。感谢你热情分享QQ779442053
        谁是我我我:@Hero_SJ 谢谢你。
        J_Knight_:@谁是我我我 还不是大神呢~ 已发~
      • Apples8023:麻烦来一份源码,谢谢博主
        335983653@qq.com
        J_Knight_:@Apples8023 不客气 已发~
      • midmirror:请来一份源码:ex.gilgamesh@foxmail.com ,谢谢博主
        midmirror:@Hero_SJ 多谢!
        J_Knight_:@midmirror 已发~
        J_Knight_:@midmirror 不要客气,等一下中午休息时间给你发~
      • d0ccbd3f98cf:楼主大神,demo呢
        J_Knight_:@glhfstar Demo是有的,但得给我你的邮箱呀
        J_Knight_:@glhfstar 表叫俺大神 :smile:
        J_Knight_:@glhfstar 等一下中午休息时间给你发~
      • Xiaoooolan:Swift时代已经到来...
        Xiaoooolan:@Hero_SJ 我收回这句话:sweat:
        J_Knight_:@Xiaoooolan 都是相通的嘛

      本文标题:斯坦福大学iOS开发公开课总结(七) :自定义视图,手势识别,绘

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