Android: 利用SurfaceView繪制股票滑動直線解決延遲問題


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,同時每次繪圖前要鎖定畫布,繪制完成后解鎖畫布。

 歡迎關注公眾號"Devin說",會不定期更新技術知識


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM