Android自定义有限制区域的图例角度自识别涂鸦工具类完结篇
作者:似曾相识2022 发布时间:2022-10-22 23:05:13
引言
上文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)进行缩放,这里缩小一半,根据实际情况调整,到此整个功能也就完成了。
来源:https://juejin.cn/post/7202996449776222268


猜你喜欢
- 1. 使用蓝牙的响应权限<uses-permission android:name="android.permission.
- feignclient https接口调用报证书错误问题最近在使用 feignclient 过程中,和第三方通过https 协议交互的时候,
- 要让项目实现 ssl 免密登录,首先需要开启 https 。所以先从 Spring Boot 如何开启 https 说起。创建服务端证书为了
- 学过Spring的小伙伴对于IOC一定不陌生,IOC:控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向
- Application对象Application对象生存期和Web应用程序生存期一样长,生存期从Web应用程序网页被访问开始,HttpApp
- Cookie和Session都是为了保持用户的访问状态,一方面为了方便业务实现,另一方面为了简化服务端的程序设计,提高访问性能。Cookie
- 大家在网上购物时都有这样一个体验,在确认订单选择收货人以及地址时,会跳转页面到我们存入网站内的所有收货信息(包含收货地址,收货人)的界面供我
- 1、启动新Activty1.1、功能分析App功能在第一个Activity输入消息点击第一个Activity的发送按钮发送消息到第二个Act
- 欢迎大家来学习本节内容,前几节我们已经学习了其他几种自定义控件,分别是Andriod 自定义控件之音频条及 Andriod 自定义控件之创建
- 本文实例为大家分享了Java身份证号码校验工具类的具体代码,供大家参考,具体内容如下import java.text.ParseExcept
- 本文实例讲述了android中ListView数据刷新时的同步方法。分享给大家供大家参考。具体实现方法如下:public class Mai
- android获取手机通讯录联系人信息private void getPhoneContacts() {
- jvm虚拟机栈的作用jvm虚拟机栈栈帧的组成jvm虚拟机栈,也叫java栈,它由一个个的栈帧组成,而栈帖由以下几个部分组成局部变量表-存储方
- 前言 侧滑的实现方式有很多方式来实现,这次总结的ViewDragHe
- 1、静态代码块①、格式在java类中(方法中不能存在静态代码块)使用static关键字和{}声明的代码块:public class Code
- 本文实例讲述了Android编程实现震动与振铃的方法。分享给大家供大家参考,具体如下:1、Android的震动实现——Vibrator类(1
- 本文实例讲述了Android编程实现向桌面添加快捷方式的方法。分享给大家供大家参考,具体如下:有时候为了使用方便,需要在桌面上添加快捷方式,
- Java8已经发布很多年了,但是很多人在开发时仍然坚持使用着Date和SimpleDateFormat进行时间操作。SimpleDateFo
- 在编程过程中一定要注意代码命名的规范性,否则在使用和维护过程中将造成很大的麻烦,这也是一种良好的编码习惯。看下面代码,除了userPass命
- 本文实例为大家分享了Unity shader实现消融效果的具体代码,供大家参考,具体内容如下效果图:shader代码:// Upgrade