Android白板签名

在开发的动作当中,有时候会遇到一些问题,尤其是电商或者银行类型的项目,会经常性的要求用户进行一个签名并进行上传,有的时候会要求签名并保存到本地。这个就涉及到了一个自定义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 --- 手指点下屏幕时调用

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 --- 手指在屏幕上滑动时调用

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) {
        // 设置贝塞尔曲线的操作点为起点和终点的一半
        float cX = (x + previousX) / 2;
        float cY = (y + previousY) / 2;
        // 二次贝塞尔,实现平滑曲线;previousX, previousY为操作点,cX, cY为终点
        mPath.quadTo(previousX, previousY, cX, cY);
        // 第二次执行时,第一次结束调用的坐标值将作为第二次调用的初始坐标值
        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" />
画板展示

当一切就绪后就只是在我们需要使用的地方进行调用就可以了,当然最好是对画板进行一个初始化并将画板清空,这里就相当于是点击下面的清空按钮,对画板进行了清空的操作

binding.lineName.setBackColor(Color.WHITE)
binding.lineName.setPaintWidth(20)
binding.lineName.setPenColor(Color.BLACK)
binding.lineName.clear()

在后面的操作当中,我们可能需要将画板总的图片进行上传到服务器或者保存下来,在这之前就需要就需要获取到画板当中的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
}

最后一定不要忘记了添加存储权限,毕竟我们的图片最终是保存到本地的嘛~

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    tools:ignore="ScopedStorage" />

虽然在manifest里面添加了读写权限,但是在Android的高版本上可能还是会保存失败,这个时候我们就需要进行动态的权限申请了,动态申请的方法有很多,可以自行发挥,嘿嘿


申请权限

最后在获取到权限之后再进行保存就完成了~

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, "没有读写权限无法保存图片哦~")
            }
        }
        override fun onDenied(permissions: MutableList<String>?, never: Boolean) {
            if (never) {
                ToastUtils.showMessage(mContext, "被永久拒绝授权,请手动授予读写权限");
                XXPermissions.startPermissionActivity(
                    this@ElectronSignUI,
                    permissions
                )
            } else {
                ToastUtils.showMessage(mContext, "获取读写权限失败")
            }
        }
    })
系统相册查看结果

代码传送门

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • 购物车功能在电商项目中可以说是一个必不可少的功能了,但是在项目当中我们还是想将这个功能给尽可能的做的好看点、可观赏...
    Poison丶Carson阅读 264评论 0 1
  • 目前的项目之中基本上都会存在版本更新的功能,分为强制更新和推荐更新,其实功能点都是一样的,推荐更新只是增加一个按钮...
    Poison丶Carson阅读 3,407评论 7 35
  • 在实际的开发中,经常会遇到一些列表数据,有的时候数据比较少我们可能会单开一个页面进行列表展示,有的时候可能会选择O...
    Poison丶Carson阅读 1,531评论 0 12
  • 在开发的过程当中,我们经常会用到各种各样的弹框样式,然而Android自带的弹框样式在UI看来是一个特别丑的存在,...
    Poison丶Carson阅读 563评论 0 0
  • 由于目前APP的上架需求,有的商城已经开始了免责声明,虽然不知道这样做是好是坏,但是需求在那我们就必须去实现了╮(...
    Poison丶Carson阅读 2,806评论 0 8