在上一篇文章中,我们已经实现了记事本APP的基本功能,本篇文章主要介绍如何实现手写板功能,以及手写素材如何保存。
手写板(手写输入/涂鸦)实现的大致思路如下:设置固定颜色的画板 -> 监听Touch事件 -> 绘制Touch路径 - > 将画板以及绘制的路径保存成一个图片文件。
废话不多说,上代码👇
首先看下布局需要做什么:
添加了一个约束布局,约束布局内加了一个图片,这个图片可以被理解为“画板本体”。
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/canvas_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible">
<ImageView
android:id="@+id/iv_image_canvas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
需要的变量: Bitmap图片素材,便于后期保存成文件。 Canvas 画布,用来作为画板。Paint画笔,用于绘制。
//需要的变量
private Bitmap mBitmap;//位图
private Canvas mCanvas;//画布
private Paint mPaint;//画笔
//记得初始化ImageView
mBackground = findViewById(R.id.iv_image_canvas);
我写的逻辑是 当点击“手写输入icon”时 对主界面进行隐藏,然后将上述的ImageView全屏展示。不说明下我怕有人照抄xml发现有个android:visibility="invisible"。
接下来就是对画板和画笔的处理👇。
mBitmap = Bitmap.createBitmap(layout.getWidth(), layout.getHeight(), Bitmap.Config.ARGB_8888);
// 创建一张画布
//这里的layout我用的是最外层的布局,有需要的可以自己给外层布局声明下findByid
mCanvas = new Canvas(mBitmap);
// 画布背景为黑色
mCanvas.drawColor(Color.BLACK);
// 创建画笔
mPaint = new Paint();
// 画笔颜色为橙色
mPaint.setColor(Color.parseColor("#FF8F1F"));
// 宽度10个像素
mPaint.setStrokeWidth(10);
// 先将背景画上
mCanvas.drawBitmap(mBitmap, new Matrix(), mPaint);
//创建缩放对象Matrix
//为控件赋值
mBackground.setImageBitmap(mBitmap);
//这是为了显示画板
mBackground.setVisibility(View.VISIBLE);
//这是为了显示画板的布局
constraintLayout.setVisibility(View.VISIBLE);
//这是一个外层布局,会挡住我得画板 我就在这里GONE了
main.setVisibility(View.GONE);
上述代码完成后,就会get到一块黑色的画板,接下来就是要对画板上的触摸手势进行识别,并绘制成路径,然后保存成图片。
对手势进行识别,并绘制成可见路径的代码如下👇:
mBackground.setOnTouchListener(new View.OnTouchListener() {
int startX;
int startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
// 获取手指按下时的x,y坐标
startX = (int) event.getX();
startY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
//获取手指移动时的x,y坐标
int endX = (int) event.getX();
int endY = (int) event.getY();
// 将开始 和 结束 坐标 绘制成一条线
mCanvas.drawLine(startX, startY, endX, endY, mPaint);
// 重置开始坐标
startX = (int) event.getX();
startY = (int) event.getY();
mBackground.setImageBitmap(mBitmap);
//再次为画板赋值
break;
}
return true;
}
});
接下来就是最后一部分了,将bitmap保存成图片资源存到手机本地
代码如下👇:
public void savePicture() {
//创建文件
File mfile = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".jpg");
//输出流
OutputStream mOutputStream;
try {
mOutputStream = new FileOutputStream(mfile);
//将bitmap资源转换成JPEG图片文件
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, mOutputStream);
mOutputStream.close();
Log.d(TAG, "savePicture: " + mfile .getPath());
} catch (IOException e) {
e.printStackTrace();
}
}
至于如何在记事本APP中插入手写输入的图片,我会单独写一篇的,同时也会把如何向记事本中加入Camera图片以及如何向记事本中加入语音资源文件一起写出来。
最后附上一张实现效果图 👇:
扩展功能以及源码我会逐渐更新在公众号中(二两仙气儿),毕竟我也不能一直摸鱼(狗头)。
上一篇文章连接:从无到有,一步一步实现记事本APP(一)