项目需要所以进行研究,本人自定义view刚起步,不对的地方请轻喷。先看效果图:
实现过程:
1、继承view,构造方法中进行初始化paint及path
public ElectronicSign(Context context) {
super(context);
init();
}
public ElectronicSign(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ElectronicSign(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
gesturePaint = new Paint();
gesturePaint.setAntiAlias(true);
gesturePaint.setStyle(Paint.Style.STROKE);
gesturePaint.setStrokeWidth(defaultPaintWidth);
gesturePaint.setColor(Color.BLACK);
gesturePath = new Path();
}
2、目的就是记录为了手写的轨迹,所以要监听touch事件的按下和移动事件
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDown(event);
break;
case MotionEvent.ACTION_MOVE:
touchMove(event);
break;
}
return true;
}
在手指按下的时候记录按下的坐标,将path移动到该坐标作为起始坐标
private void touchDown(MotionEvent event) {
startX = event.getX();
startY = event.getY();
gesturePath.moveTo(startX, startY);
}
在手指移动的时候则获取移动到的坐标,然后根据path的quadTo得到平滑的贝赛尔曲线,记录此时的坐标作为下次的起始坐标
private void touchMove(MotionEvent event) {
float x = event.getX();
float y = event.getY();
if (Math.abs(x - startX) > 10 || Math.abs(y - startY) > 10) {//降低功耗
float controalX = (x + startX) / 2;
float controalY = (y + startY) / 2;
gesturePath.quadTo(startX, startY, controalX, controalY);
startX = x;
startY = y;
invalidate();
}
}
其中if (Math.abs(x - startX) > 10 || Math.abs(y - startY) > 10) 判断主要是为了降低功耗,如果手指移动的距离太小,那么就不生成贝赛尔曲线,也不进行重绘,此处数值可自行调整也可不进行判断
调用了invalidate()后便会清除自定义view中ui显示的内容,然后调用onDraw()
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(gesturePath, gesturePaint);
}
onDraw()中很简单,就是在画布中用画笔将path经过的路径绘制出来,此时界面上就会显示刚手写的部分了。核心部分完成了,那么将手写的部分保存成一张图片就可以了。
public Bitmap save() {
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);//会将canvas上绘制的内容保存到bitmap中
canvas.drawPath(gesturePath, gesturePaint);
return bitmap;
}
先生成一张空的bitmap,然后new出一个新的canvas对象,将bitmap作为构造参数传入,那么在canvas上绘制成任何内容都会保存到bitmap对象当中,此时只要在该canvas上通过drawPath用刚才手势移动所用的path绘制一遍就可以了,绘制的内容也就保存到bitmap对象了。得到该bitmap对象便可以进行显示或者通过io流作为图片保存到sd上了