Using Surface View to Display Sinusoidal Curve and Imitate Oscilloscope

Keywords: Android SurfaceView

As we all know, view is redrawn by refreshing. Android system redraws the screen by sending VSYNC signals. The refresh interval is 16 Ms. If the view completes all the operations you need within 16 ms, the user will not have the sense of carton visually; and if the operation logic is too much, Especially if the interface needs to be refreshed frequently, the main thread will be blocked continuously, which will lead to picture jamming.

So Android provides a surfaceView.

1.View is mainly suitable for active updates, while surfaceView is mainly suitable for passive updates, such as frequent refreshes.

2.View refreshes the View in the main thread, and surfaceView usually refreshes the page with a sub-thread.

3.View has no double buffering mechanism in drawing, while surfaceView has already implemented double buffering mechanism in the bottom layer.

So if customized views need frequent refreshes or have a large amount of data processing when refreshing, then you can consider using surfaceView instead of View.

There is a set of templates using Surface View. Here is an example to illustrate how to use Surface View to make oscilloscope effect and draw sinusoidal wave.

package com.example.tangzh.MyView;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.example.tangzh.mylearn.R;

/**
 * Created by TangZH on 2017/4/30.
 */
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable //Inheritance and implementation of two interfaces
{
    private SurfaceHolder mHolder;
    //Used for drawing. Canvas
    private Canvas mCanvas;
    //Subthread flags
    private boolean mIsDrawing;
    //Paint brush
    private Paint mPaint;
    private Path mPath;
    //x coordinate
    private int x=0;
    //y coordinate
    private int y=400;

    public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        initView();
    }


    public MySurfaceView(Context context)
    {
        super(context);
        initView();
    }

    public MySurfaceView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        initView();
    }
    private void initView()
    {
        mHolder=getHolder();
        mHolder.addCallback(this);
        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        mIsDrawing=true;
        mPath=new Path();
        mPath.moveTo(0,400);
        mPaint=new Paint();
        mPaint.setColor(getResources().getColor(R.color.colorTheme));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(5);
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        mIsDrawing=false;
    }

    @Override
    public void run() {
        while (mIsDrawing)
        {
            draw();
            x+=5;
            y=(int)(100* Math.sin(x*2*Math.PI/180)+400);
            mPath.lineTo(x,y);
        }
    }

    private void draw() {
        try {
            mCanvas=mHolder.lockCanvas();
            //SurfaceView background
            mCanvas.drawColor(Color.WHITE);
            mCanvas.drawPath(mPath,mPaint);
        }catch (Exception e)
        {
            e.printStackTrace();
        }finally {
            if(mCanvas!=null)
                mHolder.unlockCanvasAndPost(mCanvas); //Submit canvas content
        }
    }
}


Note that the current Canvas drawing object can be obtained by using the lockCanvas() method of the SurfaceView object, which is the same as the previous Canvas object, so the previous drawing operation will be retained. If you need to erase, you can clear the screen by drawing Color () method before drawing.

Posted by simpjd on Thu, 04 Jul 2019 16:04:28 -0700