在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); } } |