iOS UI进阶05

  • Quartz2D

    • Quartz2D是二维的绘图引擎

      • 经包装的函数库,方便开发者使用。也就是说苹果帮我们封装了一套绘图的函数库
      • 用Quartz2D写的同一份代码,既可以运行在iphone上又可以运行在mac上,可以跨平台开发。
      • 开发中比较常用的是截屏/裁剪/自定义UI控件。 Quartz2D在iOS开发中的价值就是自定义UI控件。
      • 在drawRect:方法中才能获取到上下文
  • Quartz2D绘图

    • 自定义view:需要绘图,就必须重写drawRect:方法

      • 1 drawRect视图要显示的时候,才会调用,viewDidLoad后才会调用,因为那时候还没显示视图。
      • 2 作用:用来绘图
        • 画一条线
        • 1 获取图形上下文
        • CG:表示这个类在CoreGraphics框架里 Ref:引用
        • 想获取图形上下文,首先敲UIGraphics。
        • 2 拼接路径:一般开发中用贝塞尔路径,里面封装了很多东西,可以帮我画一些基本的线段,矩形,圆等等。
        • 创建贝塞尔路径
        • 起点:moveToPoint
        • 终点:addLineToPoint
        • 3 把路径添加到上下文
      • CGPath转换:UIKit框架转CoreGraphics直接CGPath就能转
        • 4> 把上下文渲染到视图,图形上下文本身不具备显示功能。
        • 5总结:首先获取图形上下文,然后描述路径,把路径添加到上下文,渲染到视图,图形上下文相当于一个内存缓存区,在内存里面操作是最快的,比直接在界面操作快多了。
        • // 什么时候调用:当前控件即将显示的时候才会调用这个方法绘制
             // 作用:绘制内容,以后只要想在一个view中绘制内容,必须在drawRect里面绘制
             - (void)drawRect:(CGRect)rect {
          
              // 绘制曲线
              // 1.获取上下文
              CGContextRef ctx = UIGraphicsGetCurrentContext();
          
              // 2.拼接路径
              UIBezierPath *path = [UIBezierPath bezierPath];
          
              // 设置起点
              [path moveToPoint:CGPointMake(10, 125)];
          
              // 描述曲线
              [path addQuadCurveToPoint:CGPointMake(240, 125) controlPoint:CGPointMake(125, 240)];
          
              [path addLineToPoint:CGPointMake(10, 125)];
          
              // 3.添加路径到上下文
              CGContextAddPath(ctx, path.CGPath);
          
              // 设置绘图状态,一定要再渲染之前
              // 设置颜色
              [[UIColor redColor] setStroke];
          
              // 设置线段的宽度
              CGContextSetLineWidth(ctx, 15);
              // 设置线段的顶角样式
              CGContextSetLineCap(ctx, kCGLineCapRound);
          
              // 设置连接样式
              CGContextSetLineJoin(ctx, kCGLineJoinRound);
          
              // 4.渲染上下文
              CGContextStrokePath(ctx);
          }
      • 画两跟不连接的线
        • 1 第二次画的时候,重新设置起点,然后画线。一个路径可以包含多条线段。
        • 2 新创建一个路径,添加到上下文。开发中建议使用这种,比较容易控制每根线。
        • // 绘制两条路径的方法
          - (void)drawTwoLine
          {
              // 1.获取上下文
              CGContextRef ctx = UIGraphicsGetCurrentContext();
          
              // 2.拼接路径,一个路径中可以保存多条线段
              UIBezierPath *path = [UIBezierPath bezierPath];
          
              [path moveToPoint:CGPointMake(10, 10)];
          
              [path addLineToPoint:CGPointMake(20, 20)];
          
              // 3.把路径添加到上下文
              CGContextAddPath(ctx, path.CGPath);
          
              // 一根线对应一个路径,只要绘制的线不连接,最好使用一根线对应一个路径的方法
              path = [UIBezierPath bezierPath];
              // 拼接另一根直线
              // 默认下一根线的起点就是上一根线的终点
              // 设置第二根线的起点
              //    [path moveToPoint:CGPointMake(20, 20)];
              // 如果想要绘制不连接的线,重新设置起点
              [path moveToPoint:CGPointMake(50, 50)];
          
              [path addLineToPoint:CGPointMake(20, 200)];
          
              // 3.把路径添加到上下文
              CGContextAddPath(ctx, path.CGPath);
          
              // 4.渲染上下文
              CGContextStrokePath(ctx);
          
          }
      • 圆弧
        • 分析:

          • 1> 圆弧属于圆的一部分,因此先要有圆,才有弧。
          • 2> 圆需要起点吗?画线需要,圆也不另外。 -3> 起点在哪? 圆心右边
          • 4> 画圆弧还需要起始角度,结束角度,方向,角度必须是弧度
          • // 画圆弧
                // Center圆心
                // radius:半径
                // startAngle起始角度
                // endAngle:结束角度
                // clockwise:Yes 顺时针 No逆时针
                CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5);
                UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:M_PI_2 clockwise:NO];
            
                [path1 stroke];
      • 画扇形
        • // 画扇形
              UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:M_PI_2 clockwise:YES];
          
              [path addLineToPoint:center];
          
              [path addLineToPoint:CGPointMake(self.bounds.size.height * 0.5 + 100, self.bounds.size.height * 0.5)];
              // 关闭路径:从路径的终点连接到起点
              [path closePath];
              // 设置填充颜色
              [[UIColor redColor] setFill];
          
              // 设置描边颜色
              [[UIColor greenColor] setStroke];
          
              //    [path stroke];
              // 如果路径不是封闭的,默认会关闭路径
              [path fill];
      • 画饼图
        • #import "PieView.h"
          
          @implementation PieView
          
          // Only override drawRect: if you perform custom drawing.
          // An empty implementation adversely affects performance during animation.
          
          - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
          {
             //重绘
              [self setNeedsDisplay];
          }
          
          - (void)drawRect:(CGRect)rect {
              // Drawing code
          
              NSArray *data = @[@25,@25,@20,@30];
          
              //圆心
              CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5);
              //角度
              CGFloat radius = self.bounds.size.width * 0.5;
              CGFloat startA = 0;
              CGFloat endA = 0;
              CGFloat angle = 0;
          
              for (NSNumber *num in data) {
                  // 画一个扇形
                  startA = endA;
                  angle = [num intValue] / 100.0 * M_PI * 2;
                  endA = startA + angle;
          
                 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
          
                  [path addLineToPoint:center];
          
                  // set:同时设置描边和填充颜色
                  [[self randomColor] set];
          
                  [path fill];
          
              }
          
          }
          
          // 随机颜色
          - (UIColor *)randomColor
          {
              CGFloat r = arc4random_uniform(256) / 255.0;
              CGFloat g = arc4random_uniform(256) / 255.0;
              CGFloat b = arc4random_uniform(256) / 255.0;
              return [UIColor colorWithRed:r green:g blue:b alpha:1];
          }
          
          @end
          效果图
          
      • 画字
        • - (void)drawRect:(CGRect)rect {
          
              NSString *str = @"hello!";
          
              // Attributes:属性
              // 给一个字符串添加属性,可以叫富文本,颜色,字体大小,空心,阴影
          
              // 利用这个属性字典给文本添加属性
              NSMutableDictionary *strAttr = [NSMutableDictionary dictionary];
              // key,value
              // 如何找到设置文本的属性key
              // 描述了字体
              strAttr[NSFontAttributeName] = [UIFont boldSystemFontOfSize:50];
          
              // 设置描边的颜色和宽度
              strAttr[NSStrokeWidthAttributeName] = @1;
          
              strAttr[NSStrokeColorAttributeName] = [UIColor redColor];
          
              NSShadow *shadow = [[NSShadow alloc] init];
          
              shadow.shadowColor = [UIColor yellowColor];
          
              shadow.shadowOffset = CGSizeMake(10, 10);
          
              shadow.shadowBlurRadius = 5;
          
              // 阴影
              strAttr[NSShadowAttributeName] = shadow;
          
              // 文字颜色
              strAttr[NSForegroundColorAttributeName] = [UIColor redColor];
          
              [str drawAtPoint:CGPointZero withAttributes:strAttr];
          
          }
           效果图:
    • 定时器实现下雪
        • #import "SnowView.h"
          
          @implementation SnowView
          
          - (void)awakeFromNib
          {
              // 设置定时器
          //    [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES];
          
              // 0.1 setNeedsDisplay 绑定一个标识,等待下次刷新的时候才会调用drawRect方法
              // 0.15 屏幕的刷新时间
          
              // 定时器
              // 每次屏幕刷新的时候就会调用,屏幕一秒刷新60次
              CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];
          
              // 只要把定时器添加到主运行循环就能自动执行
              [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
          
              // setNeedsDisplay:底层并不会马上调用drawRect,只会给当前的控件绑定一个刷新的标识,每次屏幕刷新的时候,就会把绑定了刷新(重绘)标识的控件重新刷新(绘制)一次,就会调用drawRect去重绘
          
              // 如果以后每隔一段时间需要重绘,一般不使用NSTimer,使用CADisplayLink,不会刷新的时候有延迟
          }
          
          // Only override drawRect: if you perform custom drawing.
          // An empty implementation adversely affects performance during animation.
          - (void)drawRect:(CGRect)rect {
              // Drawing code
          
              static CGFloat snowY = 0;
          
              UIImage *image = [UIImage imageNamed:@"雪花"];
          
              [image drawAtPoint:CGPointMake(0, snowY)];
          
              snowY += 10;
          
              if (snowY > rect.size.height) {
                  snowY = 0;
              }
          
          }效果图:
    • 图形上下文状态栈
        • #import "DrawView.h"
          
          @implementation DrawView
          
          // Only override drawRect: if you perform custom drawing.
          // An empty implementation adversely affects performance during animation.
          - (void)drawRect:(CGRect)rect {
              // Drawing code
              // 1.获取上下文
              CGContextRef ctx = UIGraphicsGetCurrentContext();
          
              // 2.拼接路径
              UIBezierPath *path = [UIBezierPath bezierPath];
          
              [path moveToPoint:CGPointMake(10, 125)];
          
              [path addLineToPoint:CGPointMake(240, 125)];
          
              // 3.把路径添加到上下文
              CGContextAddPath(ctx, path.CGPath);
          
              // 保存当前上下文的默认状态
              CGContextSaveGState(ctx);
          
              // 设置状态
              [[UIColor redColor] set];
          
              CGContextSetLineWidth(ctx, 20);
          
              // 渲染上下文
              CGContextStrokePath(ctx);
          
              // 创建第二根路径
              path = [UIBezierPath bezierPath];
              [path moveToPoint:CGPointMake(125, 10)];
              [path addLineToPoint:CGPointMake(125, 240)];
          
              // 添加到上下文
              CGContextAddPath(ctx, path.CGPath);
          
              // 恢复下上下文状态
              // 取出之前的保存的状态覆盖掉当前的状态
              CGContextRestoreGState(ctx);
          //    [[UIColor blackColor] set];
          //    CGContextSetLineWidth(ctx, 1);
          
              // 4.渲染上下文到view的layer
              // 在渲染之前,系统会查看下上下文的状态,根据状态去渲染
              CGContextStrokePath(ctx);
          
          }
          
          @end
          
      • 图片截屏
        • #import "ViewController.h"
          
          @interface ViewController ()
          
          @property (nonatomic, weak) UIView *cover;
          
          @property (nonatomic, assign) CGPoint oriP;
          
          @property (weak, nonatomic) IBOutlet UIImageView *imageView;
          @property (weak, nonatomic) IBOutlet UIView *view1;
          
          @end
          
          @implementation ViewController
          
          - (UIView *)cover
          {
              if (_cover == nil) {
                  UIView *view = [[UIView alloc] init];
          
                  view.backgroundColor = [UIColor blackColor];
                  view.alpha = 0.5;
          
                  _cover = view;
          
                  [self.view addSubview:view];
          
              }
              return _cover;
          }
          
          - (IBAction)pan:(UIPanGestureRecognizer *)sender {
              // 获取下当前的触摸
              CGPoint curP = [sender locationInView:_imageView];
              if (sender.state == UIGestureRecognizerStateBegan) {
                  // 记录下一开始的位置
                  _oriP = curP;
              }
          
              // 计算下黑色蒙版的frame
              CGFloat w = curP.x - _oriP.x;
              CGFloat h = curP.y - _oriP.y;
          
              self.cover.frame = CGRectMake(_oriP.x, _oriP.y, w, h);
          
              if (sender.state == UIGestureRecognizerStateEnded) { // 手指抬起
          
                  // 裁剪图片,生成一张新图片
          
                  // 开启位图上下文
                  UIGraphicsBeginImageContextWithOptions(_imageView.bounds.size, NO, 0);
          
                  // 设置裁剪区域
                  UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.cover.frame];
                  [path addClip];
          
                  // 绘制图片
                  [_imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
          
                  // 生成图片
                  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
          
                  // 关闭上下文
                  UIGraphicsEndImageContext();
          
                  _imageView.image = image;
          
                  [self.cover removeFromSuperview];
          
              }
          
          }
          @end
          效果图:截屏前
          效果图:截屏后
           
      • 图片擦除
        • #import "ViewController.h"
          
          @interface ViewController ()
          
          @end
          
          @implementation ViewController
          // 只要用户手指在图片上拖动.就会调用
          - (IBAction)pan:(UIPanGestureRecognizer *)sender {
              // 拖动的时候,擦除图片的某一部分
          
              // 获取手指的触摸点
             CGPoint curP = [sender locationInView:sender.view];
          
              // 计算擦除的frame
              CGFloat wh = 30;
              CGFloat x = curP.x - wh * 0.5;
              CGFloat y = curP.y - wh * 0.5;
          
              CGRect frame = CGRectMake(x, y, wh, wh);
          
              // 开启位图上下文
              UIGraphicsBeginImageContextWithOptions(sender.view.bounds.size, NO, 0);
          
              // 获取当前的上下文
              CGContextRef ctx = UIGraphicsGetCurrentContext();
          
              // 把控件上的内容渲染到上下文
              [sender.view.layer renderInContext:ctx];
          
              // 清除上下文中某一部分的内容
              CGContextClearRect(ctx, frame);
          
              // 生成一张新的图片
              UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
          
              // 关闭上下文
              UIGraphicsEndImageContext();
          
              // 重新显示到UIImageView
              UIImageView *imageV = (UIImageView *)sender.view;
          
              imageV.image = image;
          
          }
          
          @end
          效果图:擦除前:
          效果图:擦除部分后
时间: 2024-08-02 13:16:10

iOS UI进阶05的相关文章

[iOS UI进阶 - 0] Quiartz2D

A.简介 1. 需要掌握的 drawRect:方法的使用 常见图形的绘制:线条.多边形.圆 绘图状态的设置:文字颜色.线宽等 图形上下文状态的保存与恢复 图形上下文栈 1.基本图形绘制* 线段(线宽.线段样式)* 矩形(空心.实心.颜色)* 三角形.梯形等形状* 椭圆\圆* 圆弧* 文字绘制* 图片绘制(pattern)* 图形上下文栈 2.练习(画人) 3.模仿UIImageView 4.自定义checkbox 5.图片裁剪 6.图片水印 7.条纹背景 8.截图     2.概念 Quartz

iOS UI进阶-1.0 Quartz2D

概述 Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统.Quartz 2D能完成的工作: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成PDF 截图\裁剪图片 自定义UI控件 代码实现 绘制线条 #import "LineView.h" @implementation LineView -(void)drawRect:(CGRect)rect { // Drawing code // 1.获得图形上下文 CGContextRef

iOS UI进阶-4.0 地图与定位

在移动互联网时代,移动app能解决用户的很多生活琐事,比如 导航:去任意陌生的地方 周边:找餐馆.找酒店.找银行.找电影院 在上述应用中,都用到了地图和定位功能,在iOS开发中,要想加入这2大功能,必须基于2个框架进行开发 Map Kit :用于地图展示 Core Location :用于地理定位 2个热门专业术语 LBS :Location Based Service SoLoMo :Social Local Mobile(索罗门)

[iOS UI进阶 - 2.3] 彩票Demo v1.3

A.需求 真机调试 "关于”模块 存储开关状态 打电话.发短信 应用评分 打开其他应用 cell 在iOS6 和 iOS7的适配 block的循环引用 屏幕适配 code source:  code source: https://github.com/hellovoidworld/HelloLottery B.iOS真机测试小功能 (1)打电话 a.方法1 最简单最直接的方式:直接跳到拨号界面 1 NSURL *url = [NSURL URLWithString:@"tel://1

[iOS UI进阶 - 3.0] 触摸事件的基本处理

A.需要掌握和练习的 1.介绍事件类型2.通过按钮的事件处理引出view的事件处理3.响应者对象 --> UIResponder --> UIView4.view的拖拽* 实现触摸方法,打印查看* 介绍touches和UIEvent参数* 扩展:点哪去哪5.涂鸦6.手势解锁7.事件的产生和传递8.响应者链条 9.手势 B.概念 1.iOS有3种主要事件 触摸事件 加速计事件 远程控制事件 2.响应者对象 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事

iOS UI进阶-2.0 CALayer

在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个文本输入框.一个图标等等,这些都是UIView 其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层.在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层 @property(nonatomic,readonly,retain) CALayer *layer; 当UIView需要显示到屏幕上时,会调用drawRect

[iOS UI进阶 - 2.0] 彩票Demo v1.0

A.需求 1.模仿"网易彩票"做出有5个导航页面和相应功能的Demo 2.v1.0 版本搭建基本框架 B.搭建基本框架 1.拖入TaBarController,5个NavigationController和对应的5个UIViewController 2.配置图标和启动画面 AppIcon直接拖入图片 LaunchImage在Xcode6中需要先更改启动图使用图库的图片,而不是LaunchImage.xib 2.引入图片包 4. 按照模块分类代码包 3.底部导航--自定义TabBar (

[iOS UI进阶 - 3.1] 触摸事件的传递

A.事件的产生和传递 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中 UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow) 主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步 找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理touchesBegan-touchesMoved- touchedEnded-

iOS UI进阶-1.0网易彩票框架搭建

仿网易彩票,最终要做成的效果如下: 一.分层搭建 1.新建一个项目,Lottery.只支持7.1以上坚屏. 2.将素材全部图片全部拉到相应的文件夹里. 3.选中Lottery--右键Show in Finder ,在Lottery文件夹下新建一个Classes,并分别分层成MVC文件夹. 4.把Classes拉到Lottery项目里,整个框架结构如 二.UI搭建 分层好之后,接下来,我们搭建一下界面.使用Storyboard进行搭建. 1.点击Main.storyboard,删除原来的界面,分别