SurfaceView概述和基本使用

Android屏幕刷新一遍时间间隔为16ms,如果view能够在16ms内完成所需要执行的绘图换作,那么在视觉上,界面就是流畅的,否则就会出现卡顿现象,在很多情况下,这些逻辑处理又是必须的,为了解决这个问题,Android 引用了surfaceView,在二个方面改进了View的绘图操作:

使用双缓冲技术

自带画布,支持在子线程中更新画布内容

view和surfaceView使用场景:

当界面需要被动更新时,用view较好,比如,与手势交互的场景,因为画面的更新是依赖ontouch来完成,所以可以直接使用invalidate函数,在这种一次touch和下一次touch时间长的话,就不会产生影响

当界面需要主动刷新,使用surfaceView比较好,比如视频播放摄像头等

基本用法:

surfaceView派生View

package com.loaderman.customviewdemo;

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.MotionEvent;
import android.view.SurfaceView;


public class ViewGesturePath extends SurfaceView {
    private Paint mPaint;
    private Path mPath;
    public ViewGesturePath(Context context) {
        super(context);
        init();
    }
    public ViewGesturePath(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    public ViewGesturePath(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init(){
        setWillNotDraw(false);
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(5);
        mPaint.setColor(Color.RED);

        mPath = new Path();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int x = (int)event.getX();
        int y = (int)event.getY();
        if (event.getAction() == MotionEvent.ACTION_DOWN){
            mPath.moveTo(x,y);
            return true;
        }else if (event.getAction() == MotionEvent.ACTION_MOVE){
            mPath.lineTo(x,y);
        }
        postInvalidate();


        return super.onTouchEvent(event);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(mPath,mPaint);

    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="#ffffff"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/holo_red_dark"
        android:text="捕捉手势轨迹,画吧,少年"/>
    <com.loaderman.customviewdemo.ViewGesturePath
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

效果:

正确用法:

package com.loaderman.customviewdemo;

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.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


public class SurfaceViewGesturePath extends SurfaceView {
    private Paint mPaint;
    private Path mPath;

    public SurfaceViewGesturePath(Context context) {
        super(context);
        init();
    }

    public SurfaceViewGesturePath(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SurfaceViewGesturePath(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(5);
        mPaint.setColor(Color.RED);

        mPath = new Path();


    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int x = (int) event.getX();
        int y = (int) event.getY();
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            mPath.moveTo(x, y);
            return true;
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            mPath.lineTo(x, y);
        }
        drawCanvas();

        return super.onTouchEvent(event);
    }

    private void drawCanvas() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                SurfaceHolder surfaceHolder = getHolder();
                Canvas canvas = surfaceHolder.lockCanvas();//使用缓冲Canvas绘图

                canvas.drawPath(mPath, mPaint);

                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }).start();
    }
}

效果同上

原文地址:https://www.cnblogs.com/loaderman/p/10231916.html