• drawRect


    有了view的子类,只要重载一个方法drawRect

    -(void)drawRect:(CGRect)aRect;

    它的参数是个矩形,这个矩形就是你要重绘的区域,你可以忽略参数,它只是为了性能优化,只在固定的区域绘图.

    注意!!!

    永远不要去调用drawRect,因为drawRect不是让你调用的,而是系统会去调用的.

    那怎么去告诉系统需要重绘呢?

    你发送两个消息,setNeedsDisplay和setNeedsDisplayInRect.

    -(void)setNeedsDisplay;

    -(void)setNeedsDisplayInRect:(CGRect)aRect;

    你们可以认为初始化的时候的设置是一个点,然后晚些系统查看所有需要重绘的东西,

    然后把它们按顺序排列,因为有些东西可能会重叠,然后再非常高效的把需要的东西绘制出来.

    这样做有两个好处,一是让系统依据层的情况最优化性能,

    二是如果你的property有一些setter,当你设置的时候需要重绘,这种情况也被最优化了.

    所以你所有的setter都会调用self的setNeedsDisplay来重绘.

    如果有人用了你的view,然后调用了好几个这样的setter,只需要重绘一次.

    每个setNeedsDisplay都被一起传过去,然后一次性画出来.而不是每次都重绘.

    环境(Context)决定了你在哪绘图,所以你创建环境的方法决定了要在哪绘图.

    关于这个环境要注意的有一点,每次调用drawRect环境都是不一样的,所以不要把它保存起来,而是每次都去获取新的,

    CGContextRef context = UIGraphicsGetCurrentContext();

    这就是调用的方法,这也几乎是每个drawRect的第一行.

    CGContextRef 是个cookie,不知道到底是什么,它不是个对象,因为没有*

    当你有了环境,就可以用它来建立轨迹了,

    这里就演示一个轨迹的例子,用CGContextBeginPath(context)来传递刚刚得到的环境,

    然后就可以进行移动、添加直线弧线之类的了,

    下面的几行代码就创建了右边的那个轨迹,

    CGContextMoveToPoint(context , 75 , 10);

    CGContextAddLineToPoint(context , 160 ,150);

    CGContextAddLineToPoint(context , 10 ,150);

    再说一次左上角是(0 , 0),画轨迹而不是缩放, 

    还有CGContextClosePath(context); 它会画条线回到起始点来封闭图形,

    封闭图形不是必须的,你可以画个开放的.

    上面做的这些看起来像是在绘画,但是只有上面几行代码的话其实什么也没画,虽然轨迹被创建了,但是没有真的画到屏幕上,

    为什么会这样呢?因为你需要 描边(stroke) 或者 填充(fill) 来显示轨迹,

    在描边或设置填充之前,还可以设置图形属性,这里用了UIColor设置颜色.

    [ [ UIColor greenColor]  setFill];

    [ [ UIColor redColor] setStroke];

    注意在用这个UIColor的时候不需要指出它的环境,当你在使用对象的时候,事实上你只用到UIColor,UIFont,NSString.

    这里你使用对象的时候不用指出它的环境,它会假设你用的是当前环境,只要在前面的CGContext表面环境就可以了.

    但是这里设置了描边和填充,还是什么都没画,还需要调用CGContextDrawPath

    CGContextDrawPath(context , kCGPathFillStroke);

    这个参数kCGPathFillStroke是常量标志,表示描边和填充还是仅描边或仅填充.

    其实还可以建立一个轨迹,保存到一个轨迹变量CGPath,使用完之后还能交给其他环境继续用,

    更多功能,需要去查看文档来使用.

    Graphics State 

    图形状态,你用的最主要的是颜色,但你可以用一些复杂的,比如线宽、图案填充等,

    CGContextSetLineWidth(context , 1.0);

    CGContextSetFillPattern(context , (CGPatternRef)pattern , (CGFloat [] )components );

    图形状态有一点要小心的就是子程序(subroutines),因为比如我有了一个新环境然后设置它的图形状态,

    那么这时候我调用的子程序会怎么样呢?

    子程序里面也有自己的图形状态,这就和我的设置冲突了,

    所以对此有个机制叫push和pop环境,

    UIGraphicsPopContext();

    所以我就对开始的那个环境入栈,然后再做我要做的绘图,

    然后在出栈回到调用子程序之前的环境,

     

    在drawRect里面绘制图片

    UIImage *image="";

    [image drawAtPoint:(CGPoint) p ];//按原大小绘图

    [image drawInRect:(CGRect) r ];//会缩放图片

    [image drawAsPatternInRect:(CGRect) pathRect];//会重复绘图以填满指定的矩形区域

    你还可以用PNG或者JPG格式的二进制数据来表示图片:

  • 相关阅读:
    功能类控件
    关系类控件-明细表
    WPF MenuItem 四种角色分析
    自定义的 ListBoxItem 自适应ListBox的宽度
    由DataGridTextColumn不能获取到父级DataContext引发的思考
    GDI+中发生一般性错误的解决办法(转帖)
    WPF中RadioButton绑定数据的正确方法
    C# 使用XML序列化对象(二)
    C# 使用XML序列化对象(一)
    WPF中RadioButton的分组
  • 原文地址:https://www.cnblogs.com/lhx2015/p/4729597.html
Copyright © 2020-2023  润新知