在開發(fā)的動作當中,有時候會遇到一些問題催烘,尤其是電商或者銀行類型的項目搁进,會經(jīng)常性的要求用戶進行一個簽名并進行上傳浪感,有的時候會要求簽名并保存到本地。這個就涉及到了一個自定義view的過程了饼问,其中我們要注意的是用戶手勢的問題篮撑,在按下、移動和放開的時候做不同的動作
public boolean onTouchEvent(MotionEvent event) {
if (touch != null) touch.OnTouch(true);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDown(event);
break;
case MotionEvent.ACTION_MOVE:
isTouched = true;
if (touch != null) touch.OnTouch(false);
touchMove(event);
break;
case MotionEvent.ACTION_UP:
//將路徑畫到bitmap中匆瓜,即一次筆畫完成才去更新bitmap,而手勢軌跡是實時顯示在畫板上的未蝌。
cacheCanvas.drawPath(mPath, mGesturePaint);
mPath.reset();
break;
}
// 更新繪制
invalidate();
return true;
}
touchDown --- 手指點下屏幕時調(diào)用
private void touchDown(MotionEvent event) {
// 重置繪制路線
mPath.reset();
float x = event.getX();
float y = event.getY();
mX = x;
mY = y;
// mPath繪制的繪制起點
mPath.moveTo(x, y);
}
touchMove --- 手指在屏幕上滑動時調(diào)用
private void touchMove(MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
final float previousX = mX;
final float previousY = mY;
final float dx = Math.abs(x - previousX);
final float dy = Math.abs(y - previousY);
// 兩點之間的距離大于等于3時驮吱,生成貝塞爾繪制曲線
if (dx >= 3 || dy >= 3) {
// 設(shè)置貝塞爾曲線的操作點為起點和終點的一半
float cX = (x + previousX) / 2;
float cY = (y + previousY) / 2;
// 二次貝塞爾,實現(xiàn)平滑曲線萧吠;previousX, previousY為操作點左冬,cX, cY為終點
mPath.quadTo(previousX, previousY, cX, cY);
// 第二次執(zhí)行時,第一次結(jié)束調(diào)用的坐標值將作為第二次調(diào)用的初始坐標值
mX = x;
mY = y;
}
}
清除畫板
public void clear() {
if (cacheCanvas != null) {
isTouched = false;
//更新畫板信息
mGesturePaint.setColor(mPenColor);
cacheCanvas.drawColor(mBackColor, PorterDuff.Mode.CLEAR);
mGesturePaint.setColor(mPenColor);
invalidate();
}
}
自定義完成后其實在布局當中就是比較簡單的了纸型,直接引用就可以了
<com.carson.undergo.utils.view.LinePathView
android:id="@+id/line_name"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/colorWhite" />
畫板展示
當一切就緒后就只是在我們需要使用的地方進行調(diào)用就可以了拇砰,當然最好是對畫板進行一個初始化并將畫板清空,這里就相當于是點擊下面的清空按鈕狰腌,對畫板進行了清空的操作
binding.lineName.setBackColor(Color.WHITE)
binding.lineName.setPaintWidth(20)
binding.lineName.setPenColor(Color.BLACK)
binding.lineName.clear()
在后面的操作當中除破,我們可能需要將畫板總的圖片進行上傳到服務(wù)器或者保存下來,在這之前就需要就需要獲取到畫板當中的bitMap了琼腔,這里直接貼上方法
/**
* 獲取view生成bitmap
*/
private fun createBitMapForView(view: View): Bitmap? {
view.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
)
val width = view.width
val height = view.height
view.layout(0, 0, width, height)
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
val canvas = Canvas(bitmap)
view.draw(canvas)
canvas.save()
return bitmap
}
最后一定不要忘記了添加存儲權(quán)限瑰枫,畢竟我們的圖片最終是保存到本地的嘛~
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
雖然在manifest里面添加了讀寫權(quán)限,但是在Android的高版本上可能還是會保存失敗丹莲,這個時候我們就需要進行動態(tài)的權(quán)限申請了光坝,動態(tài)申請的方法有很多,可以自行發(fā)揮甥材,嘿嘿
申請權(quán)限
最后在獲取到權(quán)限之后再進行保存就完成了~
XXPermissions.with(mContext)
.permission(Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE)
.request(object : OnPermissionCallback {
override fun onGranted(permissions: MutableList<String>?, all: Boolean) {
if (all) {
ImageUtils.saveImageToGallery(mContext, bitmap)
binding.lineName.destroyDrawingCache()
} else {
ToastUtils.showMessage(mContext, "沒有讀寫權(quán)限無法保存圖片哦~")
}
}
override fun onDenied(permissions: MutableList<String>?, never: Boolean) {
if (never) {
ToastUtils.showMessage(mContext, "被永久拒絕授權(quán),請手動授予讀寫權(quán)限");
XXPermissions.startPermissionActivity(
this@ElectronSignUI,
permissions
)
} else {
ToastUtils.showMessage(mContext, "獲取讀寫權(quán)限失敗")
}
}
})
系統(tǒng)相冊查看結(jié)果