手写功能,撤回上一步,清空,保存 功能
16lz
2021-01-26
package com.example.handwriting;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.MotionEvent;
import android.view.View;
public class DrawView extends View{
private Paint mPaint;//画笔
private Canvas mCanvas;//画布
private Path mPath; //画笔路径
private Bitmap mBitmap;//缓存图片
private int width,height;//图片宽度。高度
private float Xdown,Ydown;//手指坐标
private boolean isDrawing = false;//是否正在绘制
// 保存Path路径的集合,用List集合来模拟栈
private static List savePath;
// 记录Path路径的对象
private DrawPath dp;
private class DrawPath {
public Path path;// 路径
public Paint paint;// 画笔
}
public DrawView(Context context, int width, int height) {//构造
super(context);
this.width = width;
this.height = height;
initWedgits();
}
private void initWedgits() {
mPaint = new Paint(Color.RED);
mPaint.setAntiAlias(true);//抗锯齿
mPaint.setStrokeWidth(3);
mPaint.setDither(true);
// 设置样式
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setColor(Color.RED);// 画笔颜色
mPath = new Path();
// 创建空缓存图片
mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
mCanvas= new Canvas(mBitmap);// 把画布内容画到空缓存图片上
savePath = new ArrayList();//撤销1
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawColor(Color.YELLOW);
canvas.drawBitmap(mBitmap, 0,0, mPaint);
if (mPath != null) {
canvas.drawPath(mPath, mPaint); // 实时的显示
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final float x = event.getX();// 记录手指摁下屏幕时的Y坐标
final float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 手指摁下时清空之前的设置
//path.reset();
mPath = new Path();
dp = new DrawPath();
dp.path = mPath;
dp.paint = mPaint;
// 设置路径起始点
mPath.moveTo(x, y);
Xdown = x;
Ydown = y;
isDrawing = true;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
// 移动下一点
mPath.quadTo(Xdown, Ydown, x, y);
// 重新设置起点
Xdown = x;
Ydown = y;
isDrawing = true;
break;
case MotionEvent.ACTION_UP:
mPath.lineTo(Xdown, Ydown);
mCanvas.drawPath(mPath, mPaint);// 手指抬起时绘制路径
//mPath.reset();// 路径重置//罪魁祸首
mPath = null;// 重新置空
isDrawing = false;
savePath.add(dp);
//撤销操作以上不成功
/*mPath.lineTo(Xdown, Ydown);
mCanvas.drawPath(mPath, mPaint);
//将一条完整的路径保存下来(相当于入栈操作)
savePath.add(dp);
mPath = null;// 重新置空
isDrawing = false;*/
invalidate();
break;
default:
break;
}
// 刷新界面
invalidate();//系统函数
return true;
}
/**
* 返回绘画状态
* @return【true:正在绘制】【false:绘制完成】
*/
public boolean getDrawState() {
return isDrawing;
}
/**
* 返回Bitmap
* @return 返回绘制的图片
*/
public Bitmap getBitmap() {
return mBitmap;
}
/**
* 清除所有图片操作
*/
public void clear() {
initWedgits();
invalidate();//刷新
}
/**
* 撤销上一步操作
*/
public void undo() {
// TODO Auto-generated method stub
mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);//111
mCanvas= new Canvas(mBitmap);// 清空画布
if (savePath != null && savePath.size() > 0) {
// 移除最后一个path,相当于出栈操作
savePath.remove(savePath.size() - 1);
Iterator iter = savePath.iterator();
while (iter.hasNext()) {
DrawPath drawPath = iter.next();
mCanvas.drawPath(drawPath.path, drawPath.paint);
}
invalidate();// 刷新
}
}
/*DrawView的代码注释都很清晰,我还是大致说下DrawView的执行逻辑吧,
DrawView继承了View也就是说具有了View的所有功能,
要实现图片绘制就要实现onDraw()方法,要实现对手指在屏幕上的轨迹绘制就需要获取轨迹坐标,
所以需要重写onTouchEvent()放法,重点在onTouchEvent()方法中。当手指摁下时我们绘制起点,
但是在绘制起点前需要先调用path.reset()方法,防止path进行二次重绘,
path的moveTo方法就是来绘制当前触摸事件的起点,摁下完成之后调用inValidate()方法进行界面刷新。
当手指移动时调用path.quadTo()方法,这个方法就是追加的意思,把新坐标点追加到path中,
手指移动之后再调用inValidate()方法进行界面刷新,最后当手指抬起时,
把在当前事件周期内的轨迹绘制到画板cacheCanvas上,最后再调用inValidate()方法进行界面刷新,
因此一次的手指移动轨迹就绘制完成,当要进行下一次的绘制,就是重复以上操作了...
*/
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.MotionEvent;
import android.view.View;
public class DrawView extends View{
private Paint mPaint;//画笔
private Canvas mCanvas;//画布
private Path mPath; //画笔路径
private Bitmap mBitmap;//缓存图片
private int width,height;//图片宽度。高度
private float Xdown,Ydown;//手指坐标
private boolean isDrawing = false;//是否正在绘制
// 保存Path路径的集合,用List集合来模拟栈
private static List
// 记录Path路径的对象
private DrawPath dp;
private class DrawPath {
public Path path;// 路径
public Paint paint;// 画笔
}
public DrawView(Context context, int width, int height) {//构造
super(context);
this.width = width;
this.height = height;
initWedgits();
}
private void initWedgits() {
mPaint = new Paint(Color.RED);
mPaint.setAntiAlias(true);//抗锯齿
mPaint.setStrokeWidth(3);
mPaint.setDither(true);
// 设置样式
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setColor(Color.RED);// 画笔颜色
mPath = new Path();
// 创建空缓存图片
mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
mCanvas= new Canvas(mBitmap);// 把画布内容画到空缓存图片上
savePath = new ArrayList
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawColor(Color.YELLOW);
canvas.drawBitmap(mBitmap, 0,0, mPaint);
if (mPath != null) {
canvas.drawPath(mPath, mPaint); // 实时的显示
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final float x = event.getX();// 记录手指摁下屏幕时的Y坐标
final float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 手指摁下时清空之前的设置
//path.reset();
mPath = new Path();
dp = new DrawPath();
dp.path = mPath;
dp.paint = mPaint;
// 设置路径起始点
mPath.moveTo(x, y);
Xdown = x;
Ydown = y;
isDrawing = true;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
// 移动下一点
mPath.quadTo(Xdown, Ydown, x, y);
// 重新设置起点
Xdown = x;
Ydown = y;
isDrawing = true;
break;
case MotionEvent.ACTION_UP:
mPath.lineTo(Xdown, Ydown);
mCanvas.drawPath(mPath, mPaint);// 手指抬起时绘制路径
//mPath.reset();// 路径重置//罪魁祸首
mPath = null;// 重新置空
isDrawing = false;
savePath.add(dp);
//撤销操作以上不成功
/*mPath.lineTo(Xdown, Ydown);
mCanvas.drawPath(mPath, mPaint);
//将一条完整的路径保存下来(相当于入栈操作)
savePath.add(dp);
mPath = null;// 重新置空
isDrawing = false;*/
invalidate();
break;
default:
break;
}
// 刷新界面
invalidate();//系统函数
return true;
}
/**
* 返回绘画状态
* @return【true:正在绘制】【false:绘制完成】
*/
public boolean getDrawState() {
return isDrawing;
}
/**
* 返回Bitmap
* @return 返回绘制的图片
*/
public Bitmap getBitmap() {
return mBitmap;
}
/**
* 清除所有图片操作
*/
public void clear() {
initWedgits();
invalidate();//刷新
}
/**
* 撤销上一步操作
*/
public void undo() {
// TODO Auto-generated method stub
mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);//111
mCanvas= new Canvas(mBitmap);// 清空画布
if (savePath != null && savePath.size() > 0) {
// 移除最后一个path,相当于出栈操作
savePath.remove(savePath.size() - 1);
Iterator
while (iter.hasNext()) {
DrawPath drawPath = iter.next();
mCanvas.drawPath(drawPath.path, drawPath.paint);
}
invalidate();// 刷新
}
}
/*DrawView的代码注释都很清晰,我还是大致说下DrawView的执行逻辑吧,
DrawView继承了View也就是说具有了View的所有功能,
要实现图片绘制就要实现onDraw()方法,要实现对手指在屏幕上的轨迹绘制就需要获取轨迹坐标,
所以需要重写onTouchEvent()放法,重点在onTouchEvent()方法中。当手指摁下时我们绘制起点,
但是在绘制起点前需要先调用path.reset()方法,防止path进行二次重绘,
path的moveTo方法就是来绘制当前触摸事件的起点,摁下完成之后调用inValidate()方法进行界面刷新。
当手指移动时调用path.quadTo()方法,这个方法就是追加的意思,把新坐标点追加到path中,
手指移动之后再调用inValidate()方法进行界面刷新,最后当手指抬起时,
把在当前事件周期内的轨迹绘制到画板cacheCanvas上,最后再调用inValidate()方法进行界面刷新,
因此一次的手指移动轨迹就绘制完成,当要进行下一次的绘制,就是重复以上操作了...
*/
}
更多相关文章
- android app 内部文件路径
- OpenGl-ES2.0 For Android(安卓)读书笔记(一)
- android虚拟键盘实现
- Android使用SurfaceView画图
- android 图片手势放大缩小
- TextView源码解析-----绘制过程
- android 下获取apk的icon
- myAndroid(Struts2+Sitemesh+Freemarker)
- 自定义开关控件(ToggleView)继承View实现