Android视图框架对于创建复杂布局非常方便。然而,这种便利是以性能为代价的。当性能至关重要的时候,Android提供了几种更强大的图形处理能力,当然难度也是随之上升了。在本节中,我将介绍:
(1)SurfaceView和TextureView类如何使用标准的Canvas对象并与单独的渲染进程结
合,得到比标准视图更好的性能;
(2)新得RenderScript框架可以被用于创建独立结构的图形渲染;
(3)OpenGL可用于一些严格的图形工作和游戏。
1、SurfaceView和TextureView类如何使用标准的Canvas对象并与单独的渲染进程结
合,得到比标准视图更好的性能;
与普通视图不同,所有在SurfaceView上的绘图都发生在一个独立的线程上。要想在SurfaceView上绘图,你必须调用SurfaceHolder的lockCanvas方法,这将返回一个Canvas对象。lockCanvas方法阻止SurfaceView更新底层界面(阻止它删除你先前画的),直到你调用响应的unlockCanvasAndPost方法为止。这消除了对界面改变同步的需求(尽管你仍然需要在进程之间同步一些字段)。你应该把对SurfaceView所有的绘制包装进lockCanvas和unlockCanvasAndPost模块中。下面我提供了两种绘制SurfaceView的方法,主要来演示lockCanvas的重要作用:
1.1 创建自己的工程,将contentView设置为自己的类(继承surfaceView)
public class MainActivity extends Activity{
private static final String TAG = "MainActivity";
private int Y_center,X_center; //Y轴的一半
private int X_width; //X轴的点数
private int Y_point[];//曲线所需要的Y轴点数
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(new exampleSurfaceView(this));
}
这里我已经将下面将要使用的变量列出,setContentView(new exampleSurfaceView(this)); 接下来我们要定义自己的新类了,继承surfaceView,这里不再使用视图了。
1.2 编写自己的exampleSurfaceView类继承surfaceView
public class exampleSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
DrawingThread mThread;
private SurfaceHolder holder;
/********************************************************************************
* 获得holder对象,实例化mThread,计算屏幕大小取出Y轴的中心高度
*
* @param context
*/
public exampleSurfaceView(Context context){
super(context);
holder = getHolder();
holder.addCallback(this);
mThread = new DrawingThread(holder);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
Y_center = dm.heightPixels/2;
X_width = dm.widthPixels;
X_center = X_width/2;
Log.i(TAG, "屏幕的一半高度为:"+Y_center+"屏幕的一半宽度为:"+X_center);
Y_point = new int[X_width];
for(int i=0; i<Y_point.length; i++){
Y_point[i] = Y_center-(int) (100 * Math.sin(i * 2 * Math.PI / 180));
}
}
//创建三角形
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
Log.i(TAG, "this is changeed format:"+arg1+"width:"+arg2+"height:"+arg3);
}
//更新surface,并起动
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mThread.keepRunning = true;
mThread.start();
}
//终止线程,回收空间
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
mThread.keepRunning = false;
boolean retry=true;
while(retry){
try{
mThread.join();
retry = false;
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
这里我们在surfaceView创建的时候开启线程,在surfaceView销毁的时候,回收线程,最后我们在把线程内容给出。
1.3 通过线程实现绘制图形。
public class DrawingThread extends Thread {
boolean keepRunning=true;
private SurfaceHolder holder;
public DrawingThread(SurfaceHolder holder) {
// TODO Auto-generated constructor stub
this.holder =holder;
}
@Override
public void run(){
Canvas c;
int count = 0;
int X_old,Y_old,X_new,Y_new;
X_old = 0;
Y_old = Y_point[X_old];
while(keepRunning){
c = null;
try{
synchronized(holder){//synchronized锁的永远是对象,获得holder对象
c = holder.lockCanvas();
c.drawColor(Color.BLACK);
Paint mPaint = new Paint(); //创建画笔
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.RED);
X_new = X_old+1;
Y_new = Y_point[X_new];
c.drawLine(X_old, Y_old, X_new, Y_new, mPaint);
c.drawText("这是第"+(count++)+"秒", X_center, Y_center, mPaint);
X_old++;
Y_old = Y_point[X_old];
if(X_old == X_width-1){
Log.i(TAG, "game over");
X_old = 1;
Y_old = Y_point[X_old];
}
Thread.sleep(10);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(c != null){
holder.unlockCanvasAndPost(c);
}
}
}
}
}
这里就实现了正弦波的绘制。图片如下:
这两个图是上面程序绘制的,不断的调用c.drawColor(Color.BLACK);来清除图层
不使用c.drawColor(Color.BLACK);
我这里是线程多次执行,绘制出来的,当然也可一在线程执行一次的时候直接绘制完毕,这里可以自己微微改动。