敞开生长之旅!这是我参加「日新方案 2 月更文应战」的第 20 天,点击查看活动详情
上文Android:完成一个自定义有限制区域的图例(视点自识别)涂鸦东西类(中)中咱们现已完成了在复杂的异形区域中涂鸦,最终生成图片保存的功用。这篇咱们将继续升华,在此基础上完成涂鸦图片方向和手势方向保持一致的功用。
首先涂鸦假如要运用自定义的图片进行涂色,咱们要怎么完成呢?其实在Paint中提供了一个着色器属性,咱们能够依据需求设置对应的着色器。
//设置着色器
public Shader setShader(Shader shader) {
// If mShader changes, cached value of native shader aren't valid, since
// old shader's pointer may be reused by another shader allocation later
if (mShader != shader) {
mNativeShader = -1;
// Release any native references to the old shader content
nSetShader(mNativePaint, 0);
}
// Defer setting the shader natively until getNativeInstance() is called
mShader = shader;
return shader;
}
着色器的完成类,很明显咱们需求的是BitmapShader:
第一个参数是bitmap,第二三个参数分别为X、Y轴的平铺模式:重复、镜像等等,咱们这儿运用重复:
//设置着色器
paint.shader = BitmapShader(
bitmap,
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT
)
有了以上的设置,依据自定义图片在限定区域内能够随意涂鸦,那咱们要怎么自动识别方向呢?此时的涂鸦图片都是按照水平方向重复平铺:
由此咱们需求解决两个点:
- 咱们需求得到一个最终视点
- 咱们需求将图片旋转某个视点
上文提到过设置着色器需求传入一个bitmap,那么咱们能够再次对图片进行一个视点的旋转,然后再将旋转后的图片传入着色器就能达到作用,第二个问题解决了。那么第一个问题,怎么得到这个视点呢?
仍是得通过触摸事件,试想,假如咱们能确定这一笔的大概视点,也就是整体趋势的视点,问题就得到了解决。所以,这儿采取获取第一个点和最终一个点两者形成的视点来核算视点:
//通过横竖切得到视点
val first = allPoints[0] //第一个点
val last = allPoints[allPoints.size-1] //最终一个点
val angle = atan2((last.y - first.y).toDouble(),(last.x - first.x).toDouble()) * (180 / Math.PI)
由于所有的点咱们都是是通过容器收集的,所以这儿直接拿到对应的那条线的第一个点和最终一个点获取视点,在设置着色器的时候运用Matrix东西对图片进行视点旋转。
//旋转+缩放
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
)
假如图例过大能够依据份额调用postScale(0.5f, 0.5f)进行缩放,这儿缩小一半,依据实际情况调整,到此整个功用也就完成了。
总结
总的来说,功用的完成仍是比较简单,最主要的是找到思路和一些逻辑顺序。首先需求一个能签名的自定义类,还需求自定义一个遮罩的ViewGroup,防止签名超出规定区域。依据用户的触摸将一个按下和抬起规定为一条线,本地保护容器来收集线条、点、各类画笔。再依据每条线的起始点核算出这条线的整体视点,用于制作图例时图例的旋转方向设置。
以上就是本篇的全部内容,希望对大家有所帮助!
敞开生长之旅!这是我参加「日新方案 2 月更文应战」的第 20 天,点击查看活动详情