开门见山,先来看下效果吧。
看到这么酷炫的效果图,不得不赞叹一下我们的设计师。然而,站在程序员的角度上看,除了酷炫之外更多的是复杂。但是,上面我们所看到的还只是最简单的一种形态而已。更加复杂的情况是当存在多个人脸的时候进行主次脸动画的切换,摄像头移动的时候动画的追踪,多个动画的之间的时序控制等问题,总之,UI展示加上各种业务逻辑使得这个动画变得异常复杂。今天我们要讲解的是剔除业务逻辑之外的单纯UI上的实现。
为什么是SurfaceView选择一种方案的同时要给出为什么不选择另一种的理由是什么。没错,为什么这里不用自定义Vew来完成绘图呢?既然自定义View也可以实现一般的动画效果,为什么还要引入SurfaceView呢?可以把View理解为一个经过系统优化的,可以用来高效执行一些帧数比较低动画的对象,但是对于灵活性更高的动画来说,View并不是最好的选择。同时,对于普通的View它们都是在应用程序的主线程中进行绘制的,我们知道在Android系统上我们不能够在主线程做一些耗时的操作,否则会引起ANR。对于一些游戏画面,或者摄像头预览、视频播放来说,它们的UI都比较复杂,而且要求能够进行高效的绘制,因此,它们的UI就不适合在应用程序的主线程中进行绘制。这时候就必须要给那些需要复杂而高效UI的视图生成一个独立的绘图表面,以及使用一个独立的线程来绘制这些视图的UI,所以SurfaceView华丽登场了。
SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制。又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应。SurfaceView 一般与SurfaceHolder.Callback配合使用,需要重写以下三个方法:
@Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { }