您的位置:首页 > 移动开发 > Android开发

Android提高21篇之二:SurfaceView的基本使用方法

2013-05-06 16:35 861 查看
上次介绍SurfaceView,SurfaceView由于可以直接从内存或者DMA等硬件接口取得图像数据,因此是个非常重要的绘图容器,这次我就用两篇文章来介绍SurfaceView的用法。网上介绍SurfaceView的用法有很多,写法也层出不同,例如继承SurfaceView类,或者继承SurfaceHolder.Callback类等,这个可以根据功能实际需要自己选择,我这里就直接在普通的用户界面调用SurfaceHolder的lockCanvas和unlockCanvasAndPost。

先来看看程序运行的截图:

截图1主要演示了直接把正弦波绘画在SurfaceView上


对比上面的左右两图,右图用.lockCanvas(null),而左图用.lockCanvas(new Rect(oldX, 0, oldX + length, getWindowManager().getDefaultDisplay().getHeight())),对比一下两个效果,由于左图是按指定Rect绘画,所以效率会比右图的全控件绘画高些,并且在清屏之后(canvas.drawColor(Color.BLACK))不会留有上次绘画的残留。

接下来贴出main.xml的源码:

package com.testSurfaceView;  
      
    import java.util.Timer;  
    import java.util.TimerTask;  
      
    import android.app.Activity;  
    import android.graphics.Canvas;  
    import android.graphics.Color;  
    import android.graphics.Paint;  
    import android.graphics.Rect;  
    import android.os.Bundle;  
    import android.util.Log;  
    import android.view.SurfaceHolder;  
    import android.view.SurfaceView;  
    import android.view.View;  
    import android.widget.Button;  
      
    public class testSurfaceView extends Activity {  
            /** Called when the activity is first created. */  
            Button btnSimpleDraw, btnTimerDraw;  
            SurfaceView sfv;  
            SurfaceHolder sfh;  
      
            private Timer mTimer;  
            private MyTimerTask mTimerTask;  
            int Y_axis[],//保存正弦波的Y轴上的点  
            centerY,//中心线  
            oldX,oldY,//上一个XY点   
            currentX;//当前绘制到的X轴上的点  
      
            @Override  
            public void onCreate(Bundle savedInstanceState) {  
                    super.onCreate(savedInstanceState);  
                    setContentView(R.layout.main);  
      
                    btnSimpleDraw = (Button) this.findViewById(R.id.Button01);  
                    btnTimerDraw = (Button) this.findViewById(R.id.Button02);  
                    btnSimpleDraw.setOnClickListener(new ClickEvent());  
                    btnTimerDraw.setOnClickListener(new ClickEvent());  
                    sfv = (SurfaceView) this.findViewById(R.id.SurfaceView01);  
                    sfh = sfv.getHolder();  
      
                    //动态绘制正弦波的定时器  
                    mTimer = new Timer();  
                    mTimerTask = new MyTimerTask();  
      
                    // 初始化y轴数据  
                    centerY = (getWindowManager().getDefaultDisplay().getHeight() - sfv  
                                    .getTop()) / 2;  
                    Y_axis = new int[getWindowManager().getDefaultDisplay().getWidth()];  
                    for (int i = 1; i < Y_axis.length; i++) {// 计算正弦波  
                            Y_axis[i - 1] = centerY  
                                            - (int) (100 * Math.sin(i * 2 * Math.PI / 180));  
                    }  
            }  
      
            class ClickEvent implements View.OnClickListener {  
      
                    @Override  
                    public void onClick(View v) {  
      
                            if (v == btnSimpleDraw) {  
                                    SimpleDraw(Y_axis.length-1);//直接绘制正弦波  
                              
                            } else if (v == btnTimerDraw) {  
                                    oldY = centerY;  
                                    mTimer.schedule(mTimerTask, 0, 5);//动态绘制正弦波  
                            }  
      
                    }  
      
            }  
      
            class MyTimerTask extends TimerTask {  
                    @Override  
                    public void run() {  
      
                            SimpleDraw(currentX);  
                            currentX++;//往前进  
                            if (currentX == Y_axis.length - 1) {//如果到了终点,则清屏重来  
                                    ClearDraw();  
                                    currentX = 0;  
                                    oldY = centerY;  
                            }  
                    }  
      
            }  
              
            /* 
             * 绘制指定区域 
             */  
            void SimpleDraw(int length) {  
                    if (length == 0)  
                            oldX = 0;  
                    Canvas canvas = sfh.lockCanvas(new Rect(oldX, 0, oldX + length,  
                                    getWindowManager().getDefaultDisplay().getHeight()));// 关键:获取画布  
                    Log.i("Canvas:",  
                                    String.valueOf(oldX) + "," + String.valueOf(oldX + length));  
      
                    Paint mPaint = new Paint();  
                    mPaint.setColor(Color.GREEN);// 画笔为绿色  
                    mPaint.setStrokeWidth(2);// 设置画笔粗细  
      
                    int y;  
                    for (int i = oldX + 1; i < length; i++) {// 绘画正弦波  
                            y = Y_axis[i - 1];  
                            canvas.drawLine(oldX, oldY, i, y, mPaint);  
                            oldX = i;  
                            oldY = y;  
                    }  
                    sfh.unlockCanvasAndPost(canvas);// 解锁画布,提交画好的图像  
            }  
      
            void ClearDraw() {  
                    Canvas canvas = sfh.lockCanvas(null);  
                    canvas.drawColor(Color.BLACK);// 清除画布  
                    sfh.unlockCanvasAndPost(canvas);  
      
            }  
    }


注意一下 for (int i = oldX + 1; i < length; i++) {// 绘画正弦波 这句,在.lockCanvas()指定Rect内减少循环画线的次数,可以提高绘图效率。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: