关于UIView及其子类重绘drawRect
转载自:
https://nezha.gitbooks.io/ios-developmentarticles/content/UIView%E7%9A%84drawRect%E9%87%8D%E7%BB%98.html
有了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格式的二进制数据来表示图片:
一些常见问题
问1:由UIImageView派生出的类,为什么在drawRect中,无法绘制矩形?但如果从UIView派出就可以?
答:苹果的官方文档说了, UIImageView是专门为显示图片做的控件,用了最优显示技术,是不让调用darwrect方法, 要调用这个方法,只能从uiview里重写。
问2:在ios开发中,为什么自定义UIView 重写drawRect方法之后,绘图区域之外为黑,合理的情况是,我没有绘制或者填充的区域应该是透明的才对啊,如果我希望没有绘制的地方为透明该如何做?
答:self.backgroundColor = [UIColor clearColor]; 并记得[super drawRect];
关于UIView及其子类重绘drawRect的更多相关文章
- iOS之 重绘机制
最近在看Core Animation , 今天来谈谈CALayer 和 UIView 中的重绘的一些认识: 我们都知道UIView里面有个成员layer,利用这个这个layer我们可以设置一些圆角,阴 ...
- iOS - 布局重绘机制相关方法的研究
iOS View布局重绘机制相关方法 布局 - (void)layoutSubviews - (void)layoutIfNeeded- (void)setNeedsLayout —————————— ...
- 继承UIView的初始化 、重绘、以及绘制图片
大家对于UIViewController的生命周期都相当了解了.但是对于继承UIView的子类能做什么,却很少有文章介绍的. 1. -initWithFrame:(CGRect)rect是view指 ...
- iPhone重绘机制drawRect
如何使用iPhone进行绘图.重绘操作iPhone的绘图操作是在UIView类的drawRect方法中完成的,所以如果我们要想在一个UIView中绘图,需要写一个扩展UIView 的类,并重写draw ...
- Phone重绘机制drawRect 转
Phone重绘机制drawRect 如何使用iPhone进行绘图.重绘操作iPhone的绘图操作是在UIView类的drawRect方法中完成的,所以如果我们要想在一个UIView中绘图,需要写一个扩 ...
- iOS重绘机制drawRect
iOS的绘图操作是在UIView类的drawRect方法中完成的,所以如果我们要想在一个UIView中绘图,需要写一个扩展UIView 的类,并重写drawRect方法,在这里进行绘图操作,程序会自动 ...
- iOS 视图:重绘与UIScrollView(内容根据iOS编程编写)
我们继续之前的 Hypnosister 应用,当用户开始触摸的时候,圆形的颜色会改变. 首先,在 JXHypnosisView 头文件中声明一个属性,用来表示圆形的颜色. #import " ...
- iOS之UI--Quartz2D的入门应用--重绘下载圆形进度条
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- 同一个页面多个CALayer重绘的办法
//知识点,CALayer的重绘,-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx 方法,CALayer的渐变色.多个CALa ...
随机推荐
- poj 2533 Longest Ordered Subsequence(LIS)
Description A numeric sequence of ai is ordered ifa1 <a2 < ... < aN. Let the subsequence of ...
- CentOS7 PostgreSQL 安装
PostgreSQL安装 安装使用yum安装 (找源 http://yum.postgresql.org/) yum install https://download.postgresql.org/p ...
- jenkins与rebotframework搭配
一.下载Jenkins 下载地址:http://mirrors.jenkins-ci.org/ 贫道比较推荐下载war包的,进入上面的地址,页面里有war的链接,各种类型各种版本的release,大家 ...
- Update Case的用法与execute执行字符串
摘自于网路:http://www.cnblogs.com/joinger/articles/1297160.html update h_crm_SafetyAccessUser set ...
- 转 如何不耍流氓的做运维之——SHELL脚本
家都是文明人,尤其是做运维的,那叫一个斯文啊.怎么能耍流氓呢?赶紧看看,编写 SHELL 脚本如何能够不耍流氓. 下面的案例,我们以 MySQL 数据库备份 SHELL 脚本的案例来进行阐述. 不记录 ...
- css的单位
如果你是一名前端开发工程师,一般px和em使用频率比较高.但是今天的重点是介绍一些我们使用很少.甚至木有听说过的单位. 一.em <style type="text/css" ...
- OpenGL红宝书第一个例子:绘制两个三角形
1. 环境配置 在这里不在做环境配置的说明,因为网上可以找到很多类似的教程,如果有需要可以@我,我也希望能帮到大家,其它的不说了,先上我的代码 2. 第一个程序代码 创建LoadShader.h #p ...
- eclipse 终极操作技巧
eclipse作为一个java开发必备软件,从用户体验来说,还是蛮一般的(按照初始设置的话),所以有必要进行一些设置上的改良,加上对一些好用的快捷键的挖掘,能让你用eclipse更加得心应手,事半功倍 ...
- 实验用rootkit
进程对比实验用得到rootkit: 1.FU rootkit 简单的来说,FU是一个隐藏进程的工具.,FU_Rootkit是开源的,用C语言编写.FU_Rootkit主程序包括2个部分:Fu.exe和 ...
- stdafx文件介绍
MSDN介绍: These files are used to build a precompiled header file Projname.pch and a precompiled types ...