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次,取两次,在取第二次的时候,栈里为空会直接挂掉)。
目录
相关文章
|
2月前
|
编解码 前端开发 Java
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发三
本文介绍了基于声明式UI范式的图形绘制与动画效果实现方法,涵盖绘制图形、添加动画效果及常见组件说明三部分内容。在绘制图形部分,详细讲解了如何通过Circle组件为食物成分表添加圆形标签,以及使用Path组件结合SVG命令绘制自定义图形(如应用Logo)。动画效果部分则展示了如何利用animateTo实现闪屏动画,包括渐出、放大效果,并设置页面跳转;同时介绍了页面间共享元素转场动画的实现方式。最后,文章列举了声明式开发范式中的各类组件及其功能,帮助开发者快速上手构建复杂交互页面。
81 11
|
1月前
|
JavaScript 前端开发 UED
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发四
本文介绍了Web组件开发与性能优化的相关内容。在Web组件开发部分,涵盖创建组件、设置样式与属性、添加事件和方法以及场景示例,如动态播放视频。性能提升方面,推荐使用数据懒加载、条件渲染替代显隐控制、Column/Row替代Flex、设置List组件宽高及调整cachedCount减少滑动白块等方法,以优化应用性能与用户体验。
122 56
|
1月前
|
编解码 UED 开发者
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发之常见布局
本文主要介绍了自适应布局与响应式布局的相关内容。自适应布局部分涵盖线性布局、层叠布局、弹性布局和网格布局,详细说明了各布局的特性及使用方法,例如线性布局中的排列、拉伸与缩放,弹性布局的方向、换行与对齐方式等。响应式布局则重点讲解了栅格系统和媒体查询,阐述如何通过栅格组件和媒体查询条件实现不同设备上的适配效果。这些技术帮助开发者灵活应对多尺寸屏幕的设计需求,提升用户体验。
139 55
|
2月前
|
存储 开发框架 API
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发二
本文详细介绍了基于声明式UI开发的健康饮食应用的设计与实现过程。内容涵盖从基础环境搭建到复杂功能实现的全流程,包括创建简单视图、构建布局(如Stack、Flex)、数据模型设计、列表与网格布局构建,以及页面跳转和数据传递等核心功能。 本文通过实际案例深入浅出地解析了声明式UI开发的关键技术和最佳实践,为开发者提供了宝贵的参考。
74 14
|
1月前
|
JavaScript 前端开发 开发者
09.HarmonyOS Next数据驱动UI开发:ForEach与动态渲染完全指南(上)
在现代前端开发中,数据驱动UI已成为主流开发范式。HarmonyOS Next的ArkTS语言和声明式UI框架完美支持这一理念,使开发者能够以更高效、更直观的方式构建复杂应用。
61 1
|
iOS开发
iOS开发UI篇—iPad开发中得modal介绍
iOS开发UI篇—iPad开发中得modal介绍 一、简单介绍   说明1:   在iPhone开发中,Modal是一种常见的切换控制器的方式     默认是从屏幕底部往上弹出,直到完全盖住后面的内容为止 说明2:   在iPad开发中,Modal的使用频率也是非常高的   对...
852 0
|
iOS开发
iOS开发UI篇—Modal简单介绍
iOS开发UI篇—Modal简单介绍 一、简单介绍 除了push之外,还有另外一种控制器的切换方式,那就是Modal 任何控制器都能通过Modal的形式展⽰出来 Modal的默认效果:新控制器从屏幕的最底部往上钻,直到盖住之前的控制器为⽌ 二、代码说明 新建一个项目,在Application的代理中添加window和控制器。
951 0

热门文章

最新文章