安卓自定义画板

包含功能:

包含  获取当前画板的截图、设置画笔样式、获取画笔样式、设置画笔宽度、获取画笔宽度、设置画笔颜色、获取画笔颜色、加载图片、获取图片位图对象、设置图片位图对象,并在画布上绘制图片、撤销上一步操作、重做上一步撤销的操作、清空所有绘图路径,重新绘制位图

 自定义视图组件

package com.zx.drawing_board;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;

public class DrawingBoard extends View {

    // 上下文对象,用于获取资源和应用程序信息
    public Context context;

    // 画布对象,用于绘制图形
    public Canvas canvas;

    // 画笔对象,用于设置绘制样式和颜色
    public Paint paint;

    // 位图对象,用于在其中进行绘制操作
    public Bitmap bitmap;

    // 绘制路径对象,记录用户绘制的路径
    public Path path;

    // 图片的URI地址
    public Uri uri;

    // 图片位图对象,用于加载图片
    private Bitmap mImageBitmap;

    // 保存用户绘制路径的栈结构
    private Stack paths = new Stack<>();

    /**
     * 构造函数,创建一个新的FingerPainterView对象
     * @param context 上下文对象,用于获取资源和应用程序信息
     */
    public DrawingBoard(Context context) {
        super(context);
        // 执行初始化方法
        init(context);
    }

    /**
     * 构造函数,创建一个新的FingerPainterView对象
     * @param context 上下文对象,用于获取资源和应用程序信息
     * @param attrs 属性集合对象,用于获取视图的自定义属性
     */
    public DrawingBoard(Context context, AttributeSet attrs) {
        super(context, attrs);

        // 执行初始化方法
        init(context);
    }

    /**
     * 构造函数,创建一个新的FingerPainterView对象
     * @param context 上下文对象,用于获取资源和应用程序信息
     * @param attrs 属性集合对象,用于获取视图的自定义属性
     * @param defStyle 样式属性,用于设置默认样式
     */
    public DrawingBoard(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // 执行初始化方法
        init(context);
    }
    /**
     * 获取当前画板的截图
     * @return 画板的截图
     */
    public Bitmap getScreenshot() {
        return Bitmap.createBitmap(bitmap);
    }
    /**
     * 初始化方法,设置默认的画笔样式和颜色
     * @param context 上下文对象,用于获取资源和应用程序信息
     */
    private void init(Context context) {
        this.context = context;

        // 创建路径对象和画笔对象
        path = new Path();
        paint = new Paint();

        // 默认的画笔样式和颜色
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeWidth(20);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setARGB(255,0,0,0);
    }

    /**
     * 设置画笔样式
     * @param brush 画笔样式
     */
    public void setBrush(Paint.Cap brush) {
        paint.setStrokeCap(brush);
    }

    /**
     * 获取画笔样式
     * @return 画笔样式
     */
    public Paint.Cap getBrush() {
        return paint.getStrokeCap();
    }

    /**
     * 设置画笔宽度
     * @param width 画笔宽度
     */
    public void setBrushWidth(int width) {
        paint.setStrokeWidth(width);
    }

    /**
     * 获取画笔宽度
     * @return 画笔宽度
     */
    public int getBrushWidth() {
        return (int) paint.getStrokeWidth();
    }

    /**
     * 设置画笔颜色
     * @param colour 画笔颜色
     */
    public void setColour(int colour) {
        paint.setColor(colour);
    }

    /**
     * 获取画笔颜色
     * @return 画笔颜色
     */
    public int getColour() {
        return paint.getColor();
    }

    /**
     * 加载图片
     * @param uri 图片的URI地址
     */
    public void load(Uri uri) {
        this.uri = uri;
    }

    /**
     * 获取图片位图对象
     * @return 图片位图对象
     */
    public Bitmap getmImageBitmap() {
        return mImageBitmap;
    }

    /**
     * 设置图片位图对象,并在画布上绘制图片
     * @param mImageBitmap 图片位图对象
     */
    public void setmImageBitmap(Bitmap mImageBitmap) {
        this.mImageBitmap = mImageBitmap;
        canvas.drawColor(Color.WHITE);
        canvas.drawBitmap(mImageBitmap, 0, 0, paint);
    }


    /**
     * 撤销上一步操作
     */
    public void undo() {
        if (!paths.isEmpty()) {
            // 移除最近的路径,并重新绘制位图
            paths.pop();
            redrawBitmap();
        }
    }

    /**
     * 重做上一步撤销的操作
     */
    public void redo() {
        if (!paths.isEmpty()) {
            // 将最近撤销的路径重新添加到绘图路径中,并重新绘制位图
            Path lastPath = paths.peek();
            paths.push(new Path(lastPath));
            redrawBitmap();
        }
    }

    /**
     * 清空所有绘图路径,重新绘制位图
     */
    public void clear() {
        paths.clear();
        redrawBitmap();
    }
    @Override
    public Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        // 保存父类视图状态
        bundle.putParcelable("superState", super.onSaveInstanceState());

        try {
            // 将位图保存到临时缓存文件中,以克服Binder事务大小限制
            File f = File.createTempFile("fingerpaint", ".png", context.getCacheDir());
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(f));
            // 将临时文件名保存到bundle中
            bundle.putString("tempfile", f.getAbsolutePath());
        } catch(IOException e) {
            Log.e("FingerPainterView", e.toString());
        }
        return bundle;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle) {
            Bundle bundle = (Bundle) state;

            try {
                // 从bundle中获取缓存文件
                File f = new File(bundle.getString("tempfile"));
                Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
                // 需要复制位图以创建可变版本
                bitmap = b.copy(b.getConfig(), true);
                b.recycle();
                f.delete();
            } catch(IOException e) {
                Log.e("FingerPainterView", e.toString());
            }

            state = bundle.getParcelable("superState");
        }
        super.onRestoreInstanceState(state);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 画布是白色的,并在顶部绘制带有alpha通道的位图
        canvas.drawColor(Color.WHITE);
        canvas.drawBitmap(bitmap, 0, 0, paint);
        // 显示当前的绘图路径
        for (Path p : paths) {
            canvas.drawPath(p, paint);
        }
        canvas.drawPath(path, paint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        // 在Activity创建后,当视图被膨胀时调用
        if(bitmap==null) {
            if(uri!=null) {
                try {
                    // 尝试加载提供的uri,并进行缩放以适应我们的画布
                    InputStream stream = context.getContentResolver().openInputStream(uri);
                    Bitmap bm = BitmapFactory.decodeStream(stream);
                    bitmap  = Bitmap.createScaledBitmap(bm, Math.max(w, h), Math.max(w, h), false);
                    stream.close();
                    bm.recycle();
                } catch(IOException e) {
                    Log.e("FingerPainterView", e.toString());
                }
            }
            else {
                // 创建一个正方形位图,以便即使在旋转到横向时也可绘制
                bitmap = Bitmap.createBitmap(Math.max(w,h), Math.max(w,h), Bitmap.Config.ARGB_8888);
            }
        }
        canvas = new Canvas(bitmap);
    }

    /**
     * 触摸事件处理方法,用于绘制路径
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 按下手指时,重置路径并移动到指定位置
                path.reset();
                path.moveTo(x, y);
                path.lineTo(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                // 手指移动时,连线到当前位置
                path.lineTo(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                // 手指抬起时,将路径保存,并重置路径
                paths.push(new Path(path));
                path.reset();
                invalidate();
                break;
        }
        return true;
    }

    /**
     * 重新绘制位图,根据当前的绘图路径
     */
    private void redrawBitmap() {
        bitmap.eraseColor(Color.WHITE);
        for (Path p : paths) {
            canvas.drawPath(p, paint);
        }
        invalidate();
    }
}

用法




    

效果

安卓自定义画板_第1张图片

你可能感兴趣的:(android)