zoukankan      html  css  js  c++  java
  • 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说",会不定期更新技术知识

  • 相关阅读:
    numpy 基础 —— np.linalg
    图像旋转后显示不完全
    opencv ---getRotationMatrix2D函数
    PS1--cannot be loaded because the execution of scripts is disabled on this system
    打开jnlp Faild to validate certificate, the application will not be executed.
    BATCH(BAT批处理命令语法)
    oracle vm virtualbox 如何让虚拟机可以上网
    merge 实现
    Windows batch,echo到文件不成功,只打印出ECHO is on.
    python2.7.6 , setuptools pip install, 报错:UnicodeDecodeError:'ascii' codec can't decode byte
  • 原文地址:https://www.cnblogs.com/devinzhang/p/2629728.html
Copyright © 2011-2022 走看看