Android 4.0的图形硬件加速及绘制技巧(3)

来源:互联网 发布:河北大学新区淘宝地址 编辑:程序博客网 时间:2024/05/30 23:03

3.Android 4.0 View的层

3.1层的分类

所有的Android版本都有能力对离屏缓冲进行渲染,或者是使用View的绘制缓冲,或者是使用Canvas.saveLayer()函数。离屏缓冲或者Layer能够有很多种应用,例如能使处理复杂view的动画效果或者应用一些合成效果都有更好地表现。例如你可以通过Canvas.saveLayer()的方式来对View做一个渐入渐出效果同时把它渲染到Layer中,然后再加上不透明效果合成后显示到屏幕上。

由Android 3.0开始你就能够通过View.setLayerType()方法对何时以及如何使用层有了更多的控制,这个API具有两个参数一个是你想使用的层类型,另外一个是可选参数Paint表明了Layer是如何被叠加的。你可以把Paint参数应用到颜色过滤上,特别是混合模式或者是对一个layer进行不透明效果。一个View可以使用如下的三种layer类型之一:

◆ LAYER_TYPE_NONE: 这个View将被按普通的方式进行渲染,但是不会返回一个离屏的缓冲,这个是默认的行为。

◆ LAYER_TYPE_HARDWARE:如果这个应用被硬件加速的话,这个View将会在硬件中渲染为硬件纹理,如果应用程序并没有被硬件加速,则其效果和LAYER_TYPE_SOFTWARE是相同的。

◆ LAYER_TYPE_SOFTWARE: 此View 通过软件渲染为一个bitmap。

3.2 层的使用

使用层的类型取决于你的目的:

3.2.1 性能:使用硬件层来渲染一个View成为硬件纹理。一旦一个View被渲染为一个层,它的绘制代码将不会得到执行,直到你调用了invalidate()函数。对于一些动画,比如透明动画可以直接应用到一个层上,这是GPU最有效率的使用方式。

3.2.2 显示效果:使用硬件或者软件层和Paint来对一个View进行特殊的视觉处理,例如你可以对一个View通过使用ColorMatrixColorFilter来实现黑白效果。

3.2.3 兼容性:使用软件层类型会强制使一个view在软件中被渲染。如果一个view是硬件加速的话(比如你设置整个应用程序是硬件加速的话),同时有渲染的问题,这是一种很简单的方式来限制硬件绘制流程。

3.3 View的层和动画的关系

当你的应用程序已经使用了硬件加速的话,硬件层能够带来更为快速和更为平滑的动画效果。当对一个复杂的View进行动画操作时,因为要进行很多的画操作,所以并不可能总是能达到60帧每秒。在这种情况下可以通过硬件层来渲染为硬件纹理来提高性能。硬件纹理操作可以用作对一个view进行动画操作,当进行动画的时候可以减少对View自身频繁的重绘。除非你改变这个view的属性(调用invalidate()方法)或者你手动的调用invalidate()。如果在你的应用中运行一个动画,但是并没有得到你想要的平滑效果,可以考虑为你要动画的view开启硬件层。

当一个View通过硬件层返回时,当所有的层叠加后最终的画面显示在屏幕时,View一些属性会被同时被处理。设置这些属性是十分有效率的,因为他们不需要View去invalidate和重绘。如下的属性将影响层的叠加,设置这些属性将会使View自动请求刷新,而且不需要对View进行重绘。

◆alpha: 改变层的透明度。

◆x, y, translationX, translationY: 改变层的位置

◆scaleX, scaleY: 改变层的大小

◆rotation, rotationX, rotationY:在3D空间内改变层的方向

◆pivotX, pivotY: 指定它进行变形的原点位置

这些属性是通过ObjectAnimator对象对一个view进行动画操作时所使用的,如果你想访问这些属性,直接调用这些属性的setter或者getter方法,例如想改变View的alpha则直接调用setAlpha()。如下的代码片段显示了一个View通过Y轴进行3D旋转。

  1. view.setLayerType(View.LAYER_TYPE_HARDWARE, null); 
  2. ObjectAnimator.ofFloat(view, "rotationY", 180).start(); 

因为硬件层会消耗视频的内存,强烈的推荐你在作动画的时候启用他们,当动画完成了之后禁用他们,你可以通过动画监听来完成这些。代码如下:

  1. View.setLayerType(View.LAYER_TYPE_HARDWARE, null); 
  2. ObjectAnimator animatorObjectAnimator.ofFloat(view, "rotationY", 180); 
  3. animator.addListener(new AnimatorListenerAdapter() { 
  4. @Override 
  5. public void onAnimationEnd(Animator animation) { 
  6. view.setLayerType(View.LAYER_TYPE_NONE, null); 
  7. }); 
  8. animator.start(); 
0 0