iOS开发UI篇—Quartz2D使用(图形上下文栈)

简介: iOS开发UI篇—Quartz2D使用(图形上下文栈) 一、qurza2d是怎么将绘图信息和绘图的属性绘制到图形上下文中去的? 说明: 新建一个项目,自定义一个view类和storyboard关联后,重写该类中的drowrect方法。

iOS开发UI篇—Quartz2D使用(图形上下文栈)

一、qurza2d是怎么将绘图信息和绘图的属性绘制到图形上下文中去的?

说明:

新建一个项目,自定义一个view类和storyboard关联后,重写该类中的drowrect方法。
画线的三个步骤:
(1)获取上下文
(2)绘图
(3)渲染
要求:画两条单独的线
代码和效果图:
 1 - (void)drawRect:(CGRect)rect
 2 {
 3     //获取上下文
 4     CGContextRef ctx=UIGraphicsGetCurrentContext();
 5     //绘图
 6     //第一条线
 7     CGContextMoveToPoint(ctx, 20, 100);
 8     CGContextAddLineToPoint(ctx, 100, 320);
 9     
10     //第二条线
11     CGContextMoveToPoint(ctx, 40, 200);
12     CGContextAddLineToPoint(ctx, 80, 100);
13     //渲染
14     CGContextStrokePath(ctx);
15     
16 }
效果图:
设置线段的宽度:两头为圆形,颜色等。
代码和效果图(发现第二条线也被渲染成第一条线的样式和状态)
 1 - (void)drawRect:(CGRect)rect
 2 {
 3     //获取上下文
 4     CGContextRef ctx=UIGraphicsGetCurrentContext();
 5     //绘图
 6     //第一条线
 7     CGContextMoveToPoint(ctx, 20, 100);
 8     CGContextAddLineToPoint(ctx, 100, 320);
 9     
10     //设置第一条线的状态
11     //设置线条的宽度
12     CGContextSetLineWidth(ctx, 12);
13     //设置线条的颜色
14     [[UIColor brownColor]set];
15     //设置线条两端的样式为圆角
16     CGContextSetLineCap(ctx,kCGLineCapRound);
17     //对线条进行渲染
18     CGContextStrokePath(ctx);
19     
20     //第二条线
21     CGContextMoveToPoint(ctx, 40, 200);
22     CGContextAddLineToPoint(ctx, 80, 100);
23     //渲染
24     CGContextStrokePath(ctx);
25     
26 }

效果图:

新的需求:要让两条线的颜色不一样,要求第二条线变成原版的样子。要达到上面的要求,有以下几种做法:

第一种做法:
在对第二条线进行设置的时候,清空它的状态
 1 - (void)drawRect:(CGRect)rect
 2 {
 3     //获取上下文
 4     CGContextRef ctx=UIGraphicsGetCurrentContext();
 5     //绘图
 6     //第一条线
 7     CGContextMoveToPoint(ctx, 20, 100);
 8     CGContextAddLineToPoint(ctx, 100, 320);
 9     
10     //设置第一条线的状态
11     //设置线条的宽度
12     CGContextSetLineWidth(ctx, 12);
13     //设置线条的颜色
14     [[UIColor brownColor]set];
15     //设置线条两端的样式为圆角
16     CGContextSetLineCap(ctx,kCGLineCapRound);
17     //对线条进行渲染
18     CGContextStrokePath(ctx);
19     
20     //第二条线
21     CGContextMoveToPoint(ctx, 40, 200);
22     CGContextAddLineToPoint(ctx, 80, 100);
23     
24     //清空状态
25     CGContextSetLineWidth(ctx, 1);
26     [[UIColor blackColor]set];
27     CGContextSetLineCap(ctx,kCGLineCapButt);
28     
29     //渲染
30     CGContextStrokePath(ctx);
31     
32 }
 
第二种做法:
把第一条线从开始绘制到渲染的代码剪切到第二条线渲染完成之后,这样先绘制并渲染了第一条线,该线并没有对绘制信息进行过设置,显示出来的第二条线即位系统默认的效果。
 1 - (void)drawRect:(CGRect)rect
 2 {
 3     //获取上下文
 4     CGContextRef ctx=UIGraphicsGetCurrentContext();
 5     //绘图
 6     
 7     //第二条线
 8     CGContextMoveToPoint(ctx, 40, 200);
 9     CGContextAddLineToPoint(ctx, 80, 100);
10     
11     //清空状态
12     //    CGContextSetLineWidth(ctx, 1);
13     //    [[UIColor blackColor]set];
14     
15     //    CGContextSetLineCap(ctx,kCGLineCapButt);
16     
17     //渲染
18     CGContextStrokePath(ctx);
19     
20     //第一条线
21     CGContextMoveToPoint(ctx, 20, 100);
22     CGContextAddLineToPoint(ctx, 100, 320);
23     
24     //设置第一条线的状态
25     //设置线条的宽度
26     CGContextSetLineWidth(ctx, 12);
27     //设置线条的颜色
28     [[UIColor brownColor]set];
29     //设置线条两端的样式为圆角
30     CGContextSetLineCap(ctx,kCGLineCapRound);
31     //对线条进行渲染
32     CGContextStrokePath(ctx);
33 }

两种方式完成的效果相同:

 
但是有的情况下,必须要先画第一条线再画第二条线,要求在交叉部分,第二条线盖在第一条线的上面。如果要求是这样,那么只能使用第一种做法,但是如果现在有新的需求,要求在这个基础上再画两条线,那就需要清空ctx中的状态很多次,很麻烦。为了解决这个问题,下面给大家介绍图形上下文栈。
 
二、绘图的完整过程
程序启动,显示自定义的view。当程序第一次显示在我们眼前的时候,程序会调用drawRect:方法,在里面获取了图形上下文(在内存中拥有了),然后利用图形上下文保存绘图信息,可以理解为图形上下文中 有一块区域用来保存绘图信息有一块区域用来保存绘图的状态(线宽,圆角,颜色)。直线不是直接绘制到view上的,可以理解为在图形上下文中 有一块单独的区域用来先绘制图形,当调用渲染方法的时候,再把绘制好的图形显示到view上去。
 
在绘制图形区域,会去保存绘图状态区域中查找对应的状态信息(线宽,圆角,颜色),然后在绘图区域把对第一条直线绘制完成。其实在渲染之前,就已经把直线在绘制图形区域画好了。
如图:
     
说明:这些示意图和本文中的程序代码块,不具备一一对应关系,只是为了说明绘图的完整过程。
调用渲染方法的时候,把绘制图形区域已经画好的图形直接显示到view上,就是我们看到的样子了。
如图:
   
画第二条的时候,如果没有对绘图状态进行重新设置,那么可以发现画第一天线的时候使用的绘图状态还保存在图形上下文中,在第二条线进行渲染之前,会根据第一条线(上一份绘图状态)对第二条线进行相应的设置,渲染后把第二条线显示到屏幕上。
参考代码:
 1 - (void)drawRect:(CGRect)rect
 2 {
 3     //获取上下文
 4     CGContextRef ctx=UIGraphicsGetCurrentContext();
 5     //绘图
 6     //第一条线
 7     CGContextMoveToPoint(ctx, 20, 100);
 8     CGContextAddLineToPoint(ctx, 100, 320);
 9     
10     //设置第一条线的状态
11     //设置线条的宽度
12     CGContextSetLineWidth(ctx, 12);
13     //设置线条的颜色
14     [[UIColor brownColor]set];
15     //设置线条两端的样式为圆角
16     CGContextSetLineCap(ctx,kCGLineCapRound);
17     //对线条进行渲染
18     CGContextStrokePath(ctx);
19     
20     //第二条线
21     CGContextMoveToPoint(ctx, 40, 200);
22     CGContextAddLineToPoint(ctx, 80, 100);
23     //渲染
24     CGContextStrokePath(ctx);
25 }
如果清空了状态,则在渲染之前,在绘制图形区域对第二条线进行绘制的时候,会去查找当前的绘图信息(已经更改——清空),根据绘图信息对第二条线进行绘制,调用渲染方法的时候把第二条线显示到view上。
参考代码:
 1 - (void)drawRect:(CGRect)rect
 2 {
 3     //获取上下文
 4     CGContextRef ctx=UIGraphicsGetCurrentContext();
 5     //绘图
 6     //第一条线
 7     CGContextMoveToPoint(ctx, 20, 100);
 8     CGContextAddLineToPoint(ctx, 100, 320);
 9     
10     //设置第一条线的状态
11     //设置线条的宽度
12     CGContextSetLineWidth(ctx, 12);
13     //设置线条的颜色
14     [[UIColor brownColor]set];
15     //设置线条两端的样式为圆角
16     CGContextSetLineCap(ctx,kCGLineCapRound);
17     //对线条进行渲染
18     CGContextStrokePath(ctx);
19     
20     //第二条线
21     CGContextMoveToPoint(ctx, 40, 200);
22     CGContextAddLineToPoint(ctx, 80, 100);
23     
24     //清空状态
25     CGContextSetLineWidth(ctx, 1);
26     [[UIColor blackColor]set];
27     CGContextSetLineCap(ctx,kCGLineCapButt);
28     
29     //渲染
30     CGContextStrokePath(ctx);
31 }

 

三、图形上下文栈
1.简单说明
在获取图形上下文之后,通过

CGContextSaveGState(ctx);

方法,把当前获取的上下文拷贝一份,保存一份最纯洁的图形上下文。
在画第二条线之前,使用CGContextRestoreGState(ctx);方法,还原开始的时候保存的那份最纯洁的图形上下文。
代码:
 1 - (void)drawRect:(CGRect)rect
 2 {
 3     //获取上下文
 4     CGContextRef ctx=UIGraphicsGetCurrentContext();
 5     //保存一份最初的图形上下文
 6     CGContextSaveGState(ctx);
 7     
 8     //绘图
 9     //第一条线
10     CGContextMoveToPoint(ctx, 20, 100);
11     CGContextAddLineToPoint(ctx, 100, 320);
12     
13     //设置第一条线的状态
14     //设置线条的宽度
15     CGContextSetLineWidth(ctx, 12);
16     //设置线条的颜色
17     [[UIColor brownColor]set];
18     //设置线条两端的样式为圆角
19     CGContextSetLineCap(ctx,kCGLineCapRound);
20     //对线条进行渲染
21     CGContextStrokePath(ctx);
22     
23     //还原开始的时候保存的那份最纯洁的图形上下文
24     CGContextRestoreGState(ctx);
25     //第二条线
26     CGContextMoveToPoint(ctx, 40, 200);
27     CGContextAddLineToPoint(ctx, 80, 100);
28     
29     //清空状态
30 //    CGContextSetLineWidth(ctx, 1);
31 //    [[UIColor blackColor]set];
32 //    CGContextSetLineCap(ctx,kCGLineCapButt);
33     
34     //渲染
35     CGContextStrokePath(ctx);
36 }
 
2.图形上下文栈机制
画第一条线的时候,会把当前的图形上下文拷贝一份保存到图形上下文栈中。
画第二条线的时候,去图形上下文栈中取出栈顶的绘图信息,作为第二条线的状态信息,第二条线的状态信息也是据此(最初保存的那份图形上下文)进行绘制。
            
注意:在栈里保存了几次,那么就可以取几次(比如不能保存了1次,取两次,在取第二次的时候,栈里为空会直接挂掉)。
目录
相关文章
|
16天前
|
前端开发 编解码 数据格式
浅谈响应式编程在企业级前端应用 UI 开发中的实践
浅谈响应式编程在企业级前端应用 UI 开发中的实践
17 0
浅谈响应式编程在企业级前端应用 UI 开发中的实践
|
27天前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
83 3
|
1天前
|
API 定位技术 iOS开发
IOS开发基础知识:什么是 Cocoa Touch?它在 iOS 开发中的作用是什么?
【4月更文挑战第18天】**Cocoa Touch** 是iOS和Mac OS X应用的核心框架,包含面向对象库、运行时系统和触摸优化工具。它提供Mac验证的开发模式,强调触控接口和性能,涵盖3D图形、音频、网络及设备访问API,如相机和GPS。是构建高效iOS应用的基础,对开发者至关重要。
8 0
|
12天前
|
XML 开发工具 Android开发
构建高效的安卓应用:使用Jetpack Compose优化UI开发
【4月更文挑战第7天】 随着Android开发不断进化,开发者面临着提高应用性能与简化UI构建流程的双重挑战。本文将探讨如何使用Jetpack Compose这一现代UI工具包来优化安卓应用的开发流程,并提升用户界面的流畅性与一致性。通过介绍Jetpack Compose的核心概念、与传统方法的区别以及实际集成步骤,我们旨在提供一种高效且可靠的解决方案,以帮助开发者构建响应迅速且用户体验优良的安卓应用。
|
16天前
|
开发工具 Swift iOS开发
利用SwiftUI构建动态用户界面:iOS开发新范式
【4月更文挑战第3天】 随着苹果不断推进其软件开发工具的边界,SwiftUI作为一种新兴的编程框架,已经逐渐成为iOS开发者的新宠。不同于传统的UIKit,SwiftUI通过声明式语法和强大的功能组合,为创建动态且响应式的用户界面提供了一种更加简洁高效的方式。本文将深入探讨如何利用SwiftUI技术构建具有高度自定义能力和响应性的用户界面,并展示其在现代iOS应用开发中的优势和潜力。
|
2月前
|
监控 API Swift
用Swift开发iOS平台上的上网行为管理监控软件
在当今数字化时代,随着智能手机的普及,人们对于网络的依赖日益增加。然而,对于一些特定场景,如家庭、学校或者企业,对于iOS设备上的网络行为进行管理和监控显得尤为重要。为了满足这一需求,我们可以利用Swift语言开发一款iOS平台上的上网行为管理监控软件。
181 2
QGS
|
3月前
|
前端开发 数据可视化 Java
手拉手JavaFX UI控件与springboot3+FX桌面开发(下)
手拉手JavaFX UI控件与springboot3+FX桌面开发
QGS
58 0
QGS
|
3月前
|
前端开发
手拉手JavaFX UI控件与springboot3+FX桌面开发(中)
手拉手JavaFX UI控件与springboot3+FX桌面开发
QGS
86 0
|
1月前
|
前端开发 搜索推荐 开发者
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍
27 0
|
1月前
|
JavaScript 前端开发 开发者
SAP UI5 控件 sap.m.ListBase 的 inset 属性的作用介绍
SAP UI5 控件 sap.m.ListBase 的 inset 属性的作用介绍
13 0