1.背景介紹
最近項目要繪製股票走勢圖,並繪製能夠跟隨手指滑動的指示線(Indicator)來精確查看股票價格和日期。如所示:
中的那條白色直線就是股票的指示線,用來跟隨手指精確確定股票的時間和股票價格。不論是繪製股票圖還是繪製指示線,我們首先想到的就是用Android中的自訂View來實現。實踐證明,使用View能夠很好地實現靜態圖片,但是對用生動影像的繪製,往往會出現延遲的現象。就如的指示線,實際用View類實現的,跟隨手指移動時,指示線就會出現延遲的現象,嚴重影響了使用者體驗,這裡自然而然的要用到SurfaceView以提高效能,提高滑動的流暢度。
2.Android中View和SurfaceView對比
下面例舉了一下二者的區別:
View SurfaceView
只能在UI主線程中更新畫面 UI主線程和新起的獨立線程中都可更新畫面
無雙緩衝機制 採用雙緩衝機制,速度快
還有其他區別希望大家補充。
3.案例
下面是該程式實現的主要代碼,隱去了資料的填充。
package com.devin;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PixelFormat;import android.graphics.PorterDuff.Mode;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;public class MyStockIndicatorView extends SurfaceView implements Callback {private SurfaceHolder surfaceHolder; private Paint paint; private float currentX;public MyStockIndicatorView(Context context) { super(context); // 初始化SurfaceHolder surfaceHolder = this.getHolder(); surfaceHolder.addCallback(this); // 讓整個介面透明 surfaceHolder.setFormat(PixelFormat.TRANSPARENT); setZOrderOnTop(true);
//初始化畫筆 paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.WHITE);
//設定介面可以點擊 setFocusable(true); }
//觸屏事件,每次響應事件後改變座標值,然後重新繪製public boolean onTouchEvent(MotionEvent event) { int eventaction = event.getAction(); int x = (int) event.getX(); switch (eventaction) { case MotionEvent.ACTION_DOWN: currentX = x; paintIndicator(); break; case MotionEvent.ACTION_UP: clearCavas(); break; case MotionEvent.ACTION_MOVE: currentX; paintIndicator(); break; case MotionEvent.ACTION_CANCEL: clearCavas(); break; } return true; }
//畫直線 private void paintIndicator() { Canvas canvas = surfaceHolder.lockCanvas();
//下面兩句用來改變原點、同時把預設的座標系轉換成笛卡爾座標系 //canvas.translate(chartLeft, getHeight()); //canvas.scale(1, -1); canvas.drawLine(currentX, 0, currentX, getHeight(), paint); surfaceHolder.unlockCanvasAndPost(canvas); }
//清屏 private void clearCavas() {
//每次繪製前要鎖定畫布 Canvas canvas = surfaceHolder.lockCanvas(); canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
//繪製完成後解鎖畫布 surfaceHolder.unlockCanvasAndPost(canvas); } public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) { } public void surfaceCreated(SurfaceHolder surfaceHolder) {
//在此處初始化資料 initData(); } public void surfaceDestroyed(SurfaceHolder holder) { }}
上述代碼關鍵地方都有注釋。對於SurfaceView的實現,需要繼承SurfaceView和實現Callback介面,同時需要實現三個方法:surfaceCreated、surfaceDestroyed、surfaceChanged方法,分別表示SurfaceView建立、銷毀、介面改變時執行的方法。在建構函式中要初始化SurfaceHolder,同時每次繪圖前要鎖定畫布,繪製完成後解鎖畫布。