1. 程式人生 > >手寫功能,撤回上一步,清空,儲存 功能

手寫功能,撤回上一步,清空,儲存 功能

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<DrawPath> 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<DrawPath>();//撤銷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<DrawPath> 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()方法進行介面重新整理,
因此一次的手指移動軌跡就繪製完成,當要進行下一次的繪製,就是重複以上操作了...
*/


}