我正在参加「掘金·启航计划」,这是我参加的第1篇文章。
前段时间比较闲,参加了掘金日新计划更文活动,至今已快三个月了。如今再次提笔,我就来分享下在这之间学习到的新技能,既是记录自己知识的积累,也希望通过自己的分享能够帮助到大家。
还记得之前曾写过一篇实现一个自定义有限制区域的图例(角度自识别)涂鸦工具类,分为上中下三篇,在最后一篇中介绍到关于涂鸦的旋转功能,这是之前的效果图:
其关键代码就是通过设置Bitmap中矩阵的角度:
//旋转+缩放
val dstbmp = Bitmap.createBitmap(
bmp, 0, 0, bmp.width, bmp.height,
Matrix().apply {
// 缩放原图
postScale(0.5f, 0.5f)
// 向左旋转45度,参数为正则向右旋转
postRotate(defaultDegrees, bmp.width / 2f, bmp.height / 2f)
}, true
)
//设置着色器
paint.shader = BitmapShader(
dstbmp,
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT
)
很明显,只要有角度产生,涂鸦出来后会出现有缝隙的排列,中间会出现大量底色,这并不是我们想要的效果。但BitmapShader的构造函数我们并没发现有关于旋转的设置,接下来就只能慢慢研究其中奥义了。
1. 测试创建一个bitmap的xml文件,平铺方式也设置为重复,再通过ImageView显示:
xml文件(test2.xml):
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@mipmap/ic_go_off"
android:tileMode="repeat"
android:dither="true"/>
布局方式:
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:rotation="-70"
android:scaleType="fitXY"
android:src="@drawable/test2" />
通过测试发现:是可以实现平铺中间无缝隙的效果的,说明我们在设置bitmap旋转那里有问题。既然在bitmap上动刀不行,那就再次转换注意力到BitmapShader。
2.BitmapShader中隐藏的mLocalMatrix
由于之前仔细看过BitmapShader中的方法和变量,并未发现猫腻,于是刚开始的方案是在创建BitmapShader时尝试看有没有设置旋转的方法,一试还真有,apply中设置角度:
paint.shader = BitmapShader(
dstbmp,
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT
)
).apply {
rotation=degrees
}
激动的运行起应用后发现确实没有缝隙了,但只要修改画笔角度,之前的角度会变成当前的角度,显然又不是我们想要的结果。出现这样的问题起初以为是每只画笔角度保存的问题,后来测试发现:这是上面代码的问题!
rotation=degrees,这个属性设置跟踪一波发现,原来设置的是View的属性,并不是BitmapShader内部属性。所以只要修改了角度,即便画笔保存了对应角度,最后重绘后都是当前设置的角度。
此时的效果其实已经相当接近需求了,看来还得是在BitmapShader中动刀。于是又仔细进入BitmapShader,它继承于Shader,于是再看看Shader:
好家伙,又看到了矩阵!!!之前设置bitmap的时候有用到过,接着还发现有个公开的setLocalMatrix(Nullable Matrix localM)的方法,总算是大出一口气。
至此每换一只笔角度也不会跟着改变,涂鸦工具算是完美实现了。
我是一个喜爱Jay、Vae的安卓开发者,喜欢结交五湖四海的兄弟姐妹,欢迎大家到沸点来点歌!