需求:实现手指在屏幕上滑动,绘制出手指的滑动轨迹,并提供一键清除轨迹的功能。
手指在屏幕上滑动,view会收到一系列的滑动事件 :DOWN —> MOVE —> … —> MOVE —> UP/CANCEL。我们知道曲线是由若干小段的直线组成的,手指在屏幕上随意滑动,肯定是曲线的路径,但是这曲线是由若干MOVE事件上报的滑动点组成的。因此,要实现这个需求,就需要监听手指的滑动事件,系统每次上报滑动事件时,我们就绘制一段直线。
我们自定义一个view叫DrawLineByFingerView,继承View。根据上面的分析,我们要关注view的onTouchEvent方法,在该方法内,我们能接收到滑动事件。
那么问题来了,我们是在onTouchEvent中接收到滑动事件,但是在View的onDraw中才能拿到Canvas画布,进而才能进行绘制操作。并且我们onDraw方法中每次传入的是一个全新的Canvas,前一次绘制的内容不会自动保存到这个新的Canvas上。因此我们还需要一个称为缓存的画布,将之前所有绘制内容 和 本次move事件的需要绘制的直线 先全部绘制到这个缓存画布上,然后在统一将这个缓存画布的内容 一次性 绘制到view的onDraw方法中传过来的画布上。
1,定义缓存画布
private Bitmap bitmapBuffer;
private Canvas bitmapCanvas;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
bitmapBuffer = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmapBuffer);
}
2,onTouchEvent方法中将本次MOVE事件上报的坐标点与上次MOVE事件(或者Down事件)的坐标,两点绘制一条Line,注意是绘制在缓存的Canvas上,然后通过invalidate()方法回调View的onDraw(),将缓存的Canvas的bitMap绘制到view的画布上。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmapBuffer, 0, 0, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
//Log.e("cyy","onTouchEvent:("+event.getX()+", "+event.getY()+")");
switch (action){
case MotionEvent.ACTION_DOWN:
preX = event.getX();
preY = event.getY();
if(bitmapBuffer.getWidth() == 1){//点过清除曲线的按钮
bitmapBuffer = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmapBuffer);
}
break;
case MotionEvent.ACTION_MOVE:
mCurrentX = event.getX();
mCurrentY = event.getY();
bitmapCanvas.drawLine(preX, preY, mCurrentX, mCurrentY, paint);
preX =mCurrentX;
preY = mCurrentY;
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
现在我们用手指多次任意滑动,在我们的自定义view上就能显示所有手指的滑动轨迹。
还有最后一个问题,我们要做一个 清除曲线 的功能,该功能可以将之前所有绘制的内容全部清除掉,方便进行下一次绘制。
View提供可供外界访问缓存bitMap的接口
public Bitmap getBitmapBuffer(){
return bitmapBuffer;
}
public void setBitmapBuffer(Bitmap bitmap){
bitmapBuffer = bitmap;
}
在Acitvity的layout中加载该view,并且在layout中添加一个 清除按钮,来实现此功能。
清除曲线路径的思路就是:将缓存bitMap的内容清空,这个bitMap对应的Canvas也就没有内容了,再将这个空的bitMap绘制到这个我们的自定义View的Canvas上。
Bitmap bitmap = mDrawLineByFingerView.getBitmapBuffer();
bitmap.recycle();
mDrawLineByFingerView.setBitmapBuffer(Bitmap.createBitmap(1,1, Bitmap.Config.ARGB_8888));
mDrawLineByFingerView.invalidate();//回调view的onDraw()方法
DONE
此系列后续持续更新。