赞
踩
包含功能:
包含 获取当前画板的截图、设置画笔样式、获取画笔样式、设置画笔宽度、获取画笔宽度、设置画笔颜色、获取画笔颜色、加载图片、获取图片位图对象、设置图片位图对象,并在画布上绘制图片、撤销上一步操作、重做上一步撤销的操作、清空所有绘图路径,重新绘制位图
自定义视图组件
- 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<Path> 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();
- }
- }
用法
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".MainActivity">
-
- <com.zx.drawing_board.DrawingBoard
- android:id="@+id/fp"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- </RelativeLayout>
效果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。