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()方法进行界面刷新,
因此一次的手指移动轨迹就绘制完成,当要进行下一次的绘制,就是重复以上操作了...
*/


}

更多相关文章

  1. android app 内部文件路径
  2. OpenGl-ES2.0 For Android(安卓)读书笔记(一)
  3. android虚拟键盘实现
  4. Android使用SurfaceView画图
  5. android 图片手势放大缩小
  6. TextView源码解析-----绘制过程
  7. android 下获取apk的icon
  8. myAndroid(Struts2+Sitemesh+Freemarker)
  9. 自定义开关控件(ToggleView)继承View实现

随机推荐

  1. Android 判断是否是数字及数字的范围
  2. Android 获取本机唯一序列号 和可变UUID
  3. Android 文件相关总结
  4. Android Error之BufferOverflowException
  5. android studio中的错误transformClasses
  6. Android:程序跳过登录界面直接进入主界面(
  7. android webservice(cfx:gbk) 乱码处理
  8. ubuntu ffmpeg 4.0.1 android 编译过程记
  9. Android常用查询网站
  10. Androidstudio 错误处理