iOS - UI设计框架

学习要点:

1.事件的触发与传递

2.控件的绘制与重绘

 

事件的触发与传递

 

我以前自己做游戏,做过整套的UI控件,对UI架构还是比较了解的,现在主流事件触发、处理机制概括来说就是,“自上而下的判断,自下而上的冒泡”。

 

当发生一个点击事件,首先判断当前交点位于哪个viewview中的哪个子view,子view中那个控件,控件中哪个位置,一层层的判断,然后再反过来一层层的回调处理函数。

 

当前主流的语言基本都是这样的做法,早期windows/MFC是直接通过消息队列来派发事件,这毫无疑问是一种比较落后的做法,造成消息传递非常困难,现在貌似已经没有语言那么做了。

 

还有就是消息的定义、归集、分类和派发等一些具体设计,比较难的地方包括焦点的转移,单选框的处理等等,就不具体展开了。

 

IOS的做法基本是就是遵循这一套原则,如果下面是UIKit的类图,可以看到NSView是从一个叫UIResponder的类派生出来的,这个类里就定义所有的触摸事件和一些转发机制,确保了所有view和从NSView派生出来的控件都有统一的事件回调接口。

 


 

 

 

控件的绘制与重绘

 

基本思想

 

界面的绘制比较复杂,早期windows的做法是简单的直接把控件都绘制在window上,但这样有一个问题,如果要作动画或者scrollView的话就需要重绘所有控件,这样会造成严重的效率问题,这也是为什么Windows平台几乎没有任何的动画特性。

 

一个基本的优化方法就是创建一个图片缓冲,比方说scrollView,可以把scrollView中的控件先渲染到一个图片,然后再绘制到窗口。在滚动时只需要移动一下图片就行了,仅当scrollView的内容发生改变是再重绘这个图片。

 

这样做可以极大的提改绘制效率,代价就是图片缓冲的额外开销。

 

但这也是必须的,做过控件底层的人就会知道控件和文字的绘制实际上是非常慢的,比绘制几万个三角形的模型快不了多少。想要出流畅的动画,这点代价是可以接受的。

 

还有一个棘手问题就是有时候会碰到控件需要横跨到父View绘图区域外的问题,这种情况不多但也不少,需要特殊处理,虽然不是不能解决,但会破坏代码的结构,所以一般来说大部分控件都不支持这种用法,超出部分将被直接切掉,除了ComboBoxCanvasMenu等少数控件。

 

IOS基本也是使用这种绘图模式,你可以使用一个单独图层来缓冲你的控件,也可以不用,看具体需求而且。

 

 

IOS中的实现

 

 UIViewiOS系统中界面元素的基础,所有的界面元素都是继承自它。UIView中可以直接绘图,方法是重载drawRect,在方法中获取相应的contextRef并绘图,这种方式绘图将会直接绘制在其父级某个view的缓冲里。

 

另一种方式是使用CALayer类。ISO中使用一个叫CALayerCore Animation Layer)的类来管理缓冲图层,他通常holdUIView下,但也可以单独使用。

 

你可以通过设置[view setWantsLayer: YES]来控制是否开启图层功能。

 

当使用CALayer的时候,UIView就只作为一个CALayer的管理器,访问它的跟绘图和跟坐标有关的属性。绘图方式是重载CALayerdrawInContext方法,这种方式将会绘制在CALayer中的缓冲图层中,然后UIView中通过调用updateLayer来将其绘制到父图层之中,你可以通过重载这个函数来做出各种动画效果。

 

 

所以你可以使用CALayer也可以不用,关键在于你是否有动画的需求。IOS中没有容器的概念,但基本就是那个意思,我的建议是对于一个整体界面单元使用CALayer,但个体控件就不要用了,毕竟移动设备内存有限。Mac上的话就无所谓了,多使用可以提高一点点效率,但Mac强大的显示能力使你很难感觉出差别。

 

关于Cell

Cocoa中绘图另一个很有特色的地方就是Cell的概念。Cocoa使用了一种策略模式,把实际的绘图逻辑封装起来,独立出一个绘图接口,CALayer会调用相应的Cell来进行绘图。这带来了很好的重用性并且可以方便的重载

 

 

了解UITableView

IOS中还有一个非常独特的控件就是UITableView。本质是说UITableView就是一个列表控件,从scrollView继承出来,但是有一个问题,就是列表可能会非常长,于是就有可能会产生一个超长的图片缓冲,在内存非常有限的手机上这是不能被接受的(好吧,其实在PC上是也是个问题,一般来说PC显卡能接受的图片素材不超过4096,手机一般要求小于2048)。

 

解决办法就是动态加载,当且仅当UITableView中的某项被显示时他才会被加载和绘制。但是显然苹果对于UITableView的优化并不到位,是个有名的问题控件,用的时候一定要注意。

 

其实我觉得优化的办法或许并不复杂,提前的缓冲几个UITableViewCell,就可以有效避免卡顿。

 

 

UI的优化

  1. 少用透明,透明控件重绘时需要重绘被其压在下面的所有控件,实际情况一般会更糟,具体看你的drawRect实现而定,比如有没有充分的分析dirtyRect。所以除非必要少用透明。
  2. 尽量的重用CellCell带来了很大的灵活性,但也带来了一大堆的Cell实例,如果可能还是尽量的重复使用同一个Cell
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值