废话少说 直接上效果 图
效果图
image.png绘制的逻辑
这个相信大家都不陌生,很多手机都会自带一个给用户涂鸦的画图板,这里我们就来写个简单的 例子,首先我们分析下,实现这个东东的一些逻辑:
Q1:这个画板放在哪里?
答:View里,我们自定义一个View,在onDraw()里完成绘制,另外View还有个onTouchEvent的方法, 我们可以在获取用户的手势操作!
Q2.需要准备些什么?
答:一只画笔(Paint),一块画布(Canvas),一个路径(Path)记录用户绘制路线; 另外划线的时候,每次都是从上次拖动时间的发生点到本次拖动时间的发生点!那么之前绘制的 就会丢失,为了保存之前绘制的内容,我们可以引入所谓的"双缓冲"技术: 其实就是每次不是直接绘制到Canvas上,而是先绘制到Bitmap上,等Bitmap上的绘制完了, 再一次性地绘制到View上而已!
Q3.具体的实现流程?
答:初始化画笔,设置颜色等等一些参数;在View的onMeasure()方法中创建一个View大小的Bitmap, 同时创建一个Canvas;onTouchEvent中获得X,Y坐标,做绘制连线,最后invalidate()重绘,即调用 onDraw方法将bitmap的东东画到Canvas上!
代码:
package com.example.guide;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
;
/**
* Created by Android Studio.
* User: 薛志辉
* Date: 2019/7/11
* Describe: recharge
*/
public class MyView extends View {
private Path path;
private Paint paint;
private Canvas canvas;
private Bitmap bitmap;
private int mLastX;
private int mLastY;
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
path = new Path();
paint = new Paint();
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);//结合处为圆角
paint.setStrokeCap(Paint.Cap.ROUND);//设置转弯处为圆角
paint.setStrokeWidth(20);//设置画笔的宽度
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measuredHeight = getMeasuredHeight();
int measuredWidth = getMeasuredWidth();
//以src为原图,创建新的图像,指定新图像的高宽以及是否变。
bitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawPath();
canvas.drawBitmap(bitmap,0,0,null);
}
public void drawPath(){
canvas.drawPath(path,paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastX=x;
mLastY=y;
//移动起点 移动下一次操作的起点位置
path.moveTo(mLastX,mLastY);
break;
case MotionEvent.ACTION_MOVE:
//该方法返回x的绝对值
int dx = Math.abs(x - mLastX);
int dy = Math.abs(y - mLastY);
if (dx>3 ||dy>3) {
//连接直线 添加上一个点到当前点之间的直线到Path
path.lineTo(x,y);
}
mLastY=y;
mLastX=x;
break;
}
//刷新界面
invalidate();
return true;
}
}
网友评论