广告位联系
返回顶部
分享到

Android自定义有限制区域图例角度自识别涂鸦工具类中篇

Android 来源:互联网 作者:佚名 发布时间:2023-03-01 22:30:27 人浏览
摘要

上文Android:实现一个自定义有限制区域的图例(角度自识别)涂鸦工具类(上)中我们已经实现了自定义View签名的功能,包含撤回、清除方法。但我们最终要实现的功能还不止如此,

上文Android:实现一个自定义有限制区域的图例(角度自识别)涂鸦工具类(上)中我们已经实现了自定义View签名的功能,包含撤回、清除方法。但我们最终要实现的功能还不止如此,这篇我们就来说说给限制区域内签名的实现过程。

试想,既然是自定义View了,那么如果要限制用户在指定区域内签名,最好的办法不是在触摸的时候通过坐标点的判断添加一些拦截吗?没错,起初我也是这么想的,但是再看到限制区域的图形后,我陷入了深深的沉思......

没错,就是这样的图,这还是其中的一张,后期指不定还会有多少张这样形状复杂的图。单看组成就不得了,都是些大小不一的圆相交相切,圆心散落在各个位置。但从自定义角度绘制这样的图形相信难度也不小,就更不要说通过坐标点的计算来拦截触摸事件的方式限制签名范围了。

此时绝望的我突然想起之前项目中的一个上传图片功能,当时是利用了ViewGroup作为遮罩来简单实现的,那么,这个功能其实也可如此。我们大可不必大费周章的采用触摸事件判断呀,超出范围如果使用画布遮挡其实也能满足。结合项目需求最后涂鸦完成后,需要生成图片,我们也可通过View自带的Draw方法生成图片,咱们说干就干。

首先,自定义一个ViewGroup(作为遮罩、生成图片使用)

1

2

3

4

5

6

7

8

9

10

11

12

13

class FaceViewGroup(context: Context, attrs: AttributeSet? = null) :

    LinearLayout(context, attrs, 0) {

    private var mWith = 0

    private var mHight = 0

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        mWith = MeasureSpec.getSize(widthMeasureSpec)

        mHight = MeasureSpec.getSize(heightMeasureSpec)

    }

    override fun dispatchDraw(canvas: Canvas?) {

        ......

    }

}

这里我们需要了解下dispatchDraw方法:

绘制 ViewGroup 中的子 View 时,会调用 dispatchDraw(Canvas canvas),需要注意的是,是在绘制 ViewGroup 自己之后,也就是在 onDraw(Canvas canvas) 之后。

最后才会触发这个方法,所以利用它绘制遮罩再合适不过,我们可以让UI将各种复杂的图形切出来保存再本地,再利用dispatchDraw方法中的画布将图片绘制在中心。切图时需要注意,我们需要绘制的区域需要透明。

1

2

3

4

5

6

7

8

//本地区域图

val bitmap = BitmapFactory.decodeResource(resources,R.mipmap.ic_face)

//绘制到ViewGroup中

canvas?.drawBitmap(bitmap, (mWith-bitmap.width)/2f, (mHight-bitmap.height)/2f, Paint().apply {

            color = Color.WHITE

            isAntiAlias = true

            style = Paint.Style.FILL

        })

在Xml:

1

2

3

4

5

6

7

8

9

10

<com.example.FaceViewGroup

    android:id="@+id/group"

    android:layout_width="414dp"

    android:layout_height="280dp">

    <com.example.SignatureView

        android:id="@+id/linePath"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:layout_margin="2dp" />

</com.example.FaceViewGroup>

SignatureView就是我们上篇讲到的自定义View,运行起来发现效果还不错,确实实现了限制的问题,虽然不是真正意义上的限制,但效果一样,满足需求了。最后生成图片:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

val bitmap: Bitmap = Bitmap.createBitmap(

    resources.displayMetrics,

    binding.group.width,

    binding.group.height,

    Bitmap.Config.ARGB_8888

)

val canvas = Canvas(bitmap)

binding.group.setBackgroundColor(ContextCompat.getColor(this, R.color.white))

//解决白底问题

canvas.drawRect(

    Rect(

        0,

        0,

        bitmap.width,

        bitmap.height

    ), Paint().apply {

        color = Color.WHITE

        style = Paint.Style.FILL

    })

binding.group.draw(canvas)

这里说下,如果不设置背景色,通过View的draw方式生成的图片是黑底的。另外还有个值得注意的点,如果使用了三方ui适配方案,你会发现无论怎么调整视图和Bitmap最后生成的图片和实际绘制看到的图片存在问题—绘制的内容偏离了限制区域,最终发现需要进行适配,也就是这一步,参考资料:

1

2

3

4

5

6

7

//这里需要添加resources.displayMetrics才能适配宽高

val bitmap: Bitmap = Bitmap.createBitmap(

    resources.displayMetrics,

    binding.group.width,

    binding.group.height,

    Bitmap.Config.ARGB_8888

)

最开始一直以为是横竖屏的切换导致位置偏移,实则是使用了AndroidAutoSize使得尺寸发生变化,所以在创建Bitmap时需要将适配过后的displayMetrics传入。到此,我们就完成了异性区域内涂鸦功能。

总结

有时候不能被固定思维所困住,换种思路或许能让复杂的问题轻松解决,但还是需要多积累经验才行。如果没有之前的自定义View和上传图片的经验,或许实现上述功能还不能找到简单的实现方式。好了,这篇就先介绍到这里,下篇我们将基于本篇的实现上,添加根据手势自动判断方向,实现图例按照手势移动的方向显示。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://juejin.cn/post/7202625823668715577
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计