自定义控件取代SurfaceView

 

        白板应用使用SurfaceView总让我感觉有点恶心,为了让它的双重缓冲不会搞出闪屏效应还得搞一个缓冲位图,先写到位图再把位图写到SurfaceView中,还要LockCanvas和UnlockCanvas轮番调用,实在恶心。

        所以我直接继承了View,然后用一个Canvas让用户可以绘制图像进去,调用drawPath和drawBitmap等函数后直接调用View的invalidate渲染到系统回调过来的、用于显示自定义View画面的Canvas中即可,比SurfaceView用起来方便一些。

 

代码如下:

NewSurfaceView(用于画上Bitmap、Path等的用途):

package cjz.project.canvasTry;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import cjz.project.maptry.R;

/**
 * Created by cjz on 2019/5/7.
 */

public class NewSurfaceView extends View{
    private Bitmap canvasBitmap = null;
    private Canvas canvas = null;

    public NewSurfaceView(Context context) {
        super(context);
    }

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

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.i("宽,高", String.format("getMeasuredWidth: %d, getMeasuredHeight: %d", getMeasuredWidth(), getMeasuredHeight()));
        if(canvasBitmap == null){
            canvasBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
            canvas = new Canvas(canvasBitmap);
        } else {
            if(getMeasuredWidth() != canvasBitmap.getWidth() || getMeasuredHeight() != canvasBitmap.getHeight()){
                canvasBitmap.recycle();
                canvasBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
                canvas = new Canvas(canvasBitmap);
            }
        }
    }

    public void drawColor(int color){
        canvas.drawColor(color);
        invalidate();
    }

    public void drawPath(Path path, Paint paint){
        canvas.drawPath(path, paint);
        invalidate();
    }

    public void drawPath(Path path, Paint paint, Rect dirty){
        canvas.drawPath(path, paint);
        invalidate(dirty);
    }

    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
        canvas.drawBitmap(bitmap, left, top, paint);
        invalidate();
    }

    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)  {
        canvas.drawBitmap(bitmap, src, dst, paint);
        invalidate();
    }

    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
        canvas.drawBitmap(bitmap, src, dst, paint);
        invalidate();
    }

    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
        canvas.drawBitmap(bitmap, matrix, paint);
        invalidate();
    }

//    public void translate(float dx, float dy) {
//        Camera camera = new Camera();
//        camera.translate(dx,dy, 0);
//        camera.applyToCanvas(canvas);
//        invalidate();
//    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(canvasBitmap,0f, 0f, null);
    }
}

 

 

MyNewSurfaceView(NewSurfaceView子类,用于画线Demo):

package cjz.project.canvasTry;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * Created by cjz on 2019/5/7.
 */

public class MyNewSurfaceView extends NewSurfaceView{
    private PointF prevLoc = new PointF();
    private Paint paint;
    public MyNewSurfaceView(Context context) {
        super(context);
        init();
    }

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

    }

    public MyNewSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }

    private void init(){
        if(paint == null) {
            paint = new Paint();
            paint.setColor(Color.RED);
            paint.setStrokeWidth(3f);
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.STROKE);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //return super.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                if(event.getPointerCount() == 1){
                    prevLoc.set(event.getX(), event.getY());
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if(event.getPointerCount() == 1) {
                    Path path = new Path();
                    path.moveTo(prevLoc.x, prevLoc.y);
                    path.lineTo(event.getX(), event.getY());
                    prevLoc.set(event.getX(), event.getY());
//                drawPath(path, paint, new Rect((int)(event.getX() - paint.getStrokeWidth()), (int)(event.getY() - paint.getStrokeWidth()),
//                        (int)(event.getX() + paint.getStrokeWidth()), (int)(event.getY() + paint.getStrokeWidth()) ));
//                drawPath(path, paint, new Rect(3,3,5,5));
                    drawPath(path, paint);
                } else if(event.getPointerCount() > 1){
//                    translate(event.getX() - prevLoc.x, event.getY() - prevLoc.y);
                    prevLoc.set(event.getX(), event.getY());
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return true;
    }
}

 

界面XML文件:




    

    


 

 

使用效果:

自定义控件取代SurfaceView_第1张图片

你可能感兴趣的:(安卓开发)