设为首页 加入收藏

TOP

如何正确地写好一个界面(二)
2017-10-12 13:04:27 】 浏览:10101
Tags:如何 正确 一个 界面
设备开发的,比如最重要的坐标系统。因此,我们也就不难理解为何UIView/NSView在CALayer 上做了一层封装。

以上,是UIView于CALayer的主要的关系。

 

2.2 Offscreen Render

当你尚在懵懂未知的开发初期,在写UIScrollView及其子类(UITableView、UICollectionView)时,一定会遇到 滚动不流畅,经常卡顿的情况;你认真研究代码,发现你逻辑代码都放到了异步线程,主线程做的都是渲染界面的活,为什么会卡顿?然后你想老手寻求帮助,老手 会让你去掉圆角、半透明和阴影之类,App又重回丝般顺滑;你不知道为什么,问老手,他可能会很详细跟你解释一通,然后你一知半解地点点头,脑中一片茫 然;较好的情况,也许你依稀记得这么一个词:离屏渲染(Offscreen Render)。那到底什么是Offscreen Render?为什么Offscreen Render会导致卡顿?

在第一章的1.2节中有提到渲染的流程图,我们再更深入点,先看看最基本的渲染通道流程:


iOS UI Arch

引自WWDC2014 #419 Advanced Graphics and Animations for iOS Apps

注:iOS的GPU渲染机制是Tile-Based的,而Tile-Based GPU也是现在移动设备的主流;

我们再来看看需要Offscreen Render的渲染通道流程:


iOS UI Arch

引自WWDC2014 #419 Advanced Graphics and Animations for iOS Apps

一般情况下,OpenGL会将应用提交到Render Server的动画直接渲染显示(基本的Tile-Based渲染流程),但对于一些复杂的图像动画的渲染并不能直接渲染叠加显示,而是需要根据 Command Buffer分通道进行渲染之后再组合,这一组合过程中,就有些渲染通道是不会直接显示的;对比基本渲染通道流程和Masking渲染通道流程图,我们可 以看到到Masking渲染需要更多渲染通道和合并的步骤;而这些没有直接显示在屏幕的上的通道(如上图的 Pass 1 和 Pass 2)就是Offscreen Rendering Pass。

Offscreen Render为什么卡顿,从上图我们就可以知道,Offscreen Render需要更多的渲染通道,而且不同的渲染通道间切换需要耗费一定的时间,这个时间内GPU会闲置,当通道达到一定数量,对性能也会有较大的影响;

那哪些情况会Offscreen Render呢?

1) drawRect
2) layer.shouldRasterize = true;
3) 有mask或者是阴影(layer.masksToBounds, layer.shadow*);
4)Text(UILabel, CATextLayer, Core Text, etc)
...

注:layer.cornerRadius,layer.borderWidth,layer.borderColor并不会Offscreen Render,因为这些不需要加入Mask。

还有更多与Offscreen Render以及动画图形优化相关的知识,请认真观看WWDC。

参考:

 

2.3 设计与实践

以上几节,对View在开发过程中经常遇到,但并不容易深入理解的概念进行了讨论。接下来,我想脱离View的具体概念,谈谈本人在View设计和开发中的一些实践经验;

 

2.3.1 精简扁平的View层次结构

复杂的View层次结果不仅会影响渲染效率,而且也会造成代码的臃肿,会造成不可预料的问题并且难以定位;怎么样维护一个精简扁平的View层次结构呢?原则如下:

1) 尽量使用系统原生的控件;

如实现一个icon跟title上下布局的按钮,很多人习惯是使用一个view包含了一个UIButton和一个UILabel。实际上更为推荐的 方式是调整UIButon的contentInset/titleInset/imageInset三个参数来达到这个效果,非常简单,并且title有 UIButton上的展示方式和特性,如可以设置高亮颜色等;

又比如一个有着复杂一点布局结构的滚动界面,有些开发者会觉得使用UITableView/UICollectionView实现会比较复杂,有些 效果可能没办法达到,就用他们的基类UIScrollView来实现,自己造了一大套的轮子,代码可能也变得非常复杂;实际上根据我的经验,通过重写或者 是内部属性的调整是完全可以使用UITableView/UICollectionView来达到这个效果,毕竟UITableView /UICollectionView是UIScrollView的子类,功能不会减少,而会更加强大,并且我们还能利用已有的data source和delegate机制,实现设计上的解耦。

其他常见的还有UINavigationBar、UITabBar、UIToolBar等等;


2) 合理添加/删除动态View;

有些View是动态的,就是偶尔显示,偶尔隐藏。这类View有两种处理方式:增删,或者显示/隐藏。没有标准的答案,个人更推荐增删的处理方式, 即在有需要的时候添加到对应的ContainerView上,在不需要的时候将其删除。这样即可以与懒加载结合在一起,而且也能避免两个动态View的相 互影响,比如TableFooterView,或者是错误加载View。但这并不是唯一的方式,假如这个动态View所在的View层级比较简单,并且需 要动画进行动态展示,则使用显示/隐藏也是不错的处理方式。

 

2.3.2 通用控件;

每一个程序员都可以建立自己的代码库,同理,每一位移动开发程序员都可以建立自己的通用控件代码库。这个库内的控件,可以是你自己写的,也可以是优 秀的第三方开源控件。建立控件库,除了能够避免重新造轮子,大大提高我们的开发效率,还有更为重要的一点:在运用、改造、重构中掌握接口设计解耦,甚至是 架构的知识和经验。

每个App的UI设计、交互、布局和配色往往千差万别,但总脱离不出移动App这一范畴,也就决定了在某些通用的控件交互上会保持一致性,以让用户 依据自己在移动应用上的使用经验就能轻松快速上手使用,这就是App的移动性。所以通用控件的适用场景往往是很“通用”的。比如下拉刷新、加载更多、 Tab Bar、提示Tips、加载错误重新加载等等。在新的App或者功能模块上运用这些控件时,你就会思考怎么让控件更加通用,即不影响旧的逻辑,又能够适用 新的需求,这对于做界面的架构设计是非常好的锻炼。

 

2.3.3 合理运用VC在替代View组合复杂界面;

在界面开发过程中,我们常常会遇到复杂的界面,比如多页界面、多种布局方式展示多业务的首页等,但由于很大部分开发者已经对“一屏就是一个VC”这 一初学者的习惯奉为教条,写出一个庞然大View,再加上复杂的逻辑代码,这一块的代码很可能就演变成了谁都不敢动的禁区。一个VC可以管理多个VC,所 以合理的使

首页 上一页 1 2 3 4 5 下一页 尾页 2/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇OpenGL ES: iOS 自定义 UIView 响.. 下一篇如何正确地写好一个界面

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目