Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1272597
  • 博文数量: 247
  • 博客积分: 5587
  • 博客等级: 大校
  • 技术积分: 2060
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-24 13:27
文章分类
文章存档

2012年(101)

2011年(44)

2010年(102)

分类: 嵌入式

2012-09-07 10:39:20

. Android 图形系统

本着知其然,要知其所以然的精神,我探索了Android的图形系统。Android 的图形系统采用client/server架构。Server(SurfaceFlinger)主要由C++代码编写而成。Client 端代码分为两部分, 一部分是由Java提供的供应用使用的api, 另一部分则是由C++写成的底层实现。Android 图形系统的框架如下图,下面我就介绍几个概念.

Application

Java

View/widgets/canvas

 

opengl

 surface

Skia 作为Android的图形系统,由如下特征

·         高度优化的软件 rasteriser (module sgl/)

·         选择性透过 OpenGL/ES,加速特定操作,如 shader textures (module gl/)

·         动画处理能力(module animator/)

·         内建 SVG 支援 (module (svg/)

·         内建若干 image codec,如 PNG, JPEG, GIF, BMP (modules images/)

·         内建文字处理,但缺乏泰文、藏文一类复杂文字处理的能力

·         效能特性:

· image 与特定数据型态的 Copy-on-write

· 内部存储器管理,谨慎地被免 fragmentation

· Thread-safety

SurfaceFlinger
      SurfaceFlinger
在整个图形系统中担任 server 角色,它负责将各个 surface 根据 Z order 合成 (composer) 起来。

 

Surface

Android图形系统中一个重要的概念和线索是surfaceView及其子类(如 TextView, Button)要画在surface上。每个surface创建一个Canvas对象(但属性时常改变),用来管理viewsurface上的绘图操作,如画点画线。每个 canvas对象对应一个bitmap,存储画在surface上的内容。

每个Surface通常对应两个buffer,一个front buffer, 一个back buffer。其中, back buffer就是canvas绘图时对应的bitmap (研究 android _view_Surface.cpp::lockCanvas)。因此,绘画总是在back buffer上,需要更新时,则将back bufferfront buffer互换。

   除了surfaceviews, 具有相同的vievrootview 共享surface

 

Layer

surface又对应一个layer, SurfaceFlinger负责将各个layerfront buffer合成(composite)绘制 到屏幕上。

具体想进一步了解图形系统可以参看Android图形系统

总结: 理解Android 图形系统,对于编写Android 图形程序是有帮助的。当然想换个图形引擎的话,就不是那么简单,图形系统代码多达十万行左右,没有一定的功底是无法胜任的。

图形系统应用

      编写图形应用,我遵循了明确需求,建立模型,编写核心算法,实现功能的软件工程方法。

(1)    明确需求: 实现浏览图片时的酷眩效果。如下图

1.  向下触屏时,图片由上而下逐渐变大。

2.  向上触屏时,图片由下而上逐渐变小。

3.  向右触屏时,每张图片有向右滑出手机屏幕的动作。同时有新的系列图片从屏幕左边飞进来。同样向左边触屏,动作, 方向与向右屏幕相反。

4.  当点击某个图片的时候,图片放大,同时透明度达到最大。

(2)    建立模型

1. 定义图片集合(目前一个屏幕五个图形)

定义 private int[] mImageIds = { R.drawable.gallery_photo_1,

                     R.drawable.gallery_photo_2, R.drawable.gallery_photo_3,

                     R.drawable.gallery_photo_4, R.drawable.gallery_photo_5 };

   每次触屏时,更换数组的数据,达到更新图片数据的目的.

   2. 定义方向

       根据触摸的坐标值来判断上下左右.

   3. 计算图片间的间隙以及伸缩,透明度比例

   4. 采用Animation实现图片飞进,飞出的效果。

(3)    编写核心算法

目前仅实现了图片伸缩,以及透明度变化,代码如下

private void drawBitmap(Canvas canvas, int i, float diffScale, int diffAlpha) {

       int offset = myposition - i;

       if (offset != 0) {

           int alpha = 255 - Math.abs(offset) * 50 + diffAlpha;

           mPaint.setAlpha(alpha > 255 ? 255 : alpha);

 

           float scale = getScale(offset); // 根据不同位置的offset计算出缩放比例

           scale = scale * diffScale;

           // scale = (scale > 1 ? 1 : scale);

           matrix.postScale(scale, scale);

       } else {

           mPaint.setAlpha(255);

       }

 

       Bitmap bp = BitmapFactory.decodeResource(ctx.getResources(),

              mImageIds[i]);

       canvas.drawBitmap(bp, matrix, mPaint);

       matrix.reset();

}

 

鼠标控制

if (event.getAction() == event.ACTION_DOWN) {

           return true;

       }

       if (event.getAction() == event.ACTION_MOVE) {

           int p = (int) ((event.getY() - downPointY) / 5);

           direction = (p > 0) ? 1 : -1;

           diffScale += 0.01;

           diffAlpha += 10;

           this.invalidate();

           return true;

       }

       if (event.getAction() == event.ACTION_UP) {

           diffScale = 1;

           diffAlpha = 0;

           direction = 0;

           this.invalidate();

           Log.i("TAG", "up");

           return true;

       }

(4)  实现功能

哈,顺着我的思路做下去,实现功能不会很难了。 接下来你可能想到优化了, 提高性能了

阅读(1913) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~