SurfaceView与Timer实现动态绘图

来源:互联网 发布:linux破解wifi工具包 编辑:程序博客网 时间:2024/05/16 02:15

在View的绘图时,必须在UI线程中更新画面,在对于比较费时的绘图中,有可能会降低UI的响应,造成不良的用户体验。因此在android中还提供了SurfaceView用于代替View绘图,SurfaceView是在新起的单独线程中完成重新绘图。


SurfaceView完成绘图需要SurfaceHolder的配合完成。

setFixedSize(WIDTH, HEIGHT);用于设置canvas的大小

SurfaceHolder提供 lockCanvas()  用于锁定SurfaceView对象,获取画布。

lockCanvas(Rect dirty)用于锁定SurfaceView对象的Rect区的Canvas,用于更新。

unlockCanvasAndPost(canvas)用于释放canvas,实现画布画面更新。


addCallbak 回调函数,包含三个方法;

public void surfaceCreated(SurfaceHolder myHolder) 用于创建时调用

public void surfaceChanged(SurfaceHolder holder, int format,int width, int height) ,在画布内容改变时调用。

public void surfaceDestroyed(SurfaceHolder holder),销毁时调用。


TimerTask是基于Runable接口实现的线程

Timer中运行任务的方式有

schedule(task, time);    //在指定时间执行一次任务

schedule(task, firstTime, period);    //从firstTime开始,每隔period间隔,执行一次任务

schedule(task, delay);    //从现在开始,过delay时间,执行任务一次

schedule(task, delay, period);    //从现在开始,过delay时间,每隔period执行一次任务


绘制正弦,余弦函数实例

布局文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

       <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="图形" />
    <SurfaceView
        android:id="@+id/show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/Sin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Sin" />

        <Button
            android:id="@+id/Cos"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cos" />
    </LinearLayout>

 

</LinearLayout>

实例源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
public class MainActivity extends Activity {

    private Button Sin;
    private Button Cos;
    private SurfaceView surface;
    private SurfaceHolder holder;
    private Paint paint;
    final int HEIGHT = 320;     //定义大小参数
    final int WIDTH = 768;
    final int X_OFFSET = 5;
    private int cx = X_OFFSET;
    int centerY = HEIGHT / 2;
    Timer timer = new Timer();
    
    private Sintask sintask;
    private Costask costask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Sin = (Button) findViewById(R.id.Sin);
        Cos = (Button) findViewById(R.id.Cos);
        surface = (SurfaceView) findViewById(R.id.show);
        holder = surface.getHolder();
        holder.setFixedSize(WIDTH+10, HEIGHT+20);     //设置Canvas大小
        paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStrokeWidth(3);
        Sin.setOnClickListener(new SinOnClick());
        Cos.setOnClickListener(new CosOnClick());
        holder.addCallback(new Callback() {
            @Override
            public void surfaceChanged(SurfaceHolder holder, int format,
                    int width, int height) {
                drawBack(holder);
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                timer.cancel();
            }

            @Override
            public void surfaceCreated(SurfaceHolder myHolder) {
                // TODO Auto-generated method stub
                //drawBack(holder);
            }
        });
    }

    private class SinOnClick implements OnClickListener {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            drawBack(holder);
            cx = X_OFFSET;
            if (sintask != null) {
                sintask.cancel();
            }
            if (costask != null) {
                costask.cancel();
            }
            sintask = new Sintask();          //创建正弦函数绘图任务
            new Thread(sintask).start();       //启动任务
            timer.schedule(sintask, 0, 30);    //每个30ms执行一次任务
            
        }

    }

    private class CosOnClick implements OnClickListener {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            drawBack(holder);
            cx = X_OFFSET;
            if (sintask != null) {
                sintask.cancel();
            }
            if (costask != null) {
                costask.cancel();
            }
            costask = new Costask();            //创建余弦函数绘图任务
            new Thread(costask).start();        //启动任务
            timer.schedule(costask, 0, 30);    //每个30ms执行一次任务

        }
    }

    private class Sintask extends TimerTask {
        public Sintask(){
            
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            int cy = centerY
                    - (int) (100 * Math.sin((cx - 5) * 2 * Math.PI / 150));
            Canvas canvas = holder.lockCanvas(new Rect(cx, cy - 2, cx + 2,
                    cy + 2));
            canvas.drawPoint(cx,cy,paint);
            cx++;
            if (cx > WIDTH) {
                cancel();
            }
            holder.unlockCanvasAndPost(canvas);
        }
    }

    private class Costask extends TimerTask {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            int cy = centerY
                    - (int) (100 * Math.cos((cx - 5) * 2 * Math.PI / 150));
            Canvas canvas = holder.lockCanvas(new Rect(cx, cy - 2, cx + 2,cy + 2));   //获取Rect区画布
            canvas.drawPoint(cx, cy, paint);              //画点
            cx++;
            if (cx > WIDTH) {
                cancel();
            }
            holder.unlockCanvasAndPost(canvas);     //释放Canvas
        }
    }

    private void drawBack(SurfaceHolder holder) {
        Canvas canvas = holder.lockCanvas();
        // 绘制黑背景
        canvas.drawColor(Color.BLACK);
        Paint p = new Paint();
        p.setColor(Color.WHITE);
        p.setStrokeWidth(2);
        // 绘制坐标轴
        canvas.drawLine(X_OFFSET, centerY, WIDTH, centerY, p);
        canvas.drawLine(X_OFFSET, 40, X_OFFSET, HEIGHT, p);
        holder.unlockCanvasAndPost(canvas);
        holder.lockCanvas(new Rect(0, 0, 0, 0));
        holder.unlockCanvasAndPost(canvas);
    }
}
程序运行效果



0 0
原创粉丝点击