检测Android组件,Android中国地图区域检测控件的实现

我大概搜索了一番,发现网上对于Android版的中国地图控件基本没有现成的可用。

0818b9ca8b590ca3270a3433284dd417.png

网上的一种实现方法是使用png图片,然后一层层叠加,在点击的地方通过获取像素值的透明度来分发事件,最后分发到非透明的那一层来消费事件,从而检测到点击的区域,这种做法在区域少的情况下还可以,一旦区域多了,就非常耗内存。简单计算一下,就拿一张480*800的png图片来说,中国的省市加上特区大概30个,每个需要两张png,每个像素4Byte,那么需要的内存是480*800*30*2*4B=87.89MB,这么大手机内存肯定吃不消。当然如果只有几个区域几张图片那这种方法还是可以接受的。

另外一种就是使用js,做成网页,但体验可能不如原生的流畅,而且不易扩展。

因此,决定采用矢量图来绘制,效果好又不占内存。

网上提供的SVG图片应该很多,这个网上搜索下应该就能找到了。AndroidStudio有个强大的将svg图片转成vector的功能,利用它可获得类似如下的xml(源文件太多就不贴了):

0818b9ca8b590ca3270a3433284dd417.png

其中最主要的就是 pathData、name、viewportWidth、viewportHeight了。

我们知道Canvas能够通过drawPath绘制路径,然后发现pathData里的字符串其实也就是描述了路径需要的数据,那么我把pathData的内容转成Path对象就可以用Canvas绘制了。

那么问题又来了,怎么转?我其实还不是特别清楚pathData内容里的协议,想写个解析器来解析也是麻烦得不得了,花费时间久还不一定好用。转念一想,google也要解析这些内容,那么他肯定实现了这个解析器,于是就从VectorDrawableCompat这个类着手,层层跟进,发现还真有个PathParser的类,可惜是私有的,没法直接用,那么就copy一下啦,PathParser类的静态方法createPathFromPathData可以将字符串生成path对象,经过试验,的确能绘制出来,心里一万个高兴。

但问题又来了,难道我要将pathData的内容一个一个copy过来然后调用createPathFromPathData生成path对象再保存起来,这样还是麻烦,有没有直接解析整个xml然后获得path对象数组的呢?google肯定实现了,但好像没开放出来,也就是无法直接使用。

发挥探索精神的时刻到了,跟进代码,大概理顺了VectorDrawableCompat此类,原来里面有个VPathRenderer类就是用来绘制的,里面保存了从xml解析出来的一些信息,比如mViewportWidth mViewportHeight等,最主要是看到了这个

final ArrayMap mVGTargetsMap = new ArrayMap();

这个map里面就保存了我要的path信息,可是怎么得到它呢?再跟下去发现VectorDrawableCompat类里有这个方法:

Object getTargetByName(String name) {

return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);

}说明VPathRenderer的实例对象在mVectorState对象里,那么我又必须先取得这个对象的实例。

同时,在跟踪过程中知道 了ArrayMap的Object的类型,主要我用到的是VFullPath和VGroup,VGroup即是可以包含多个VFullPath,VFullPath又是继承于VPath,

VPath里有我需要的mPathName属性和toPath方法。

因此思路渐渐清晰了,我要通过反射得到VectorDrawableCompat类的mVectorState实例,再从mVectorState得到mVPathRenderer实例,再从mVPathRenderer得到mVGTargetsMap,然后再分析mVGTargetsMap里的Object类型是VFullPath还是VGroup,是VGroup还要再反射得到VFullPath,最后再从VFullPath的父类VPath反射得到mPathName和toPath方法,toPath顾名思义可以得到path对象。

这样我们就从xml拿到了path对象数组,可以愉快地进行绘制了。

绘制的时候问题又来了,一开始我是通过缩放画布来实现缩放,这个时候发现居然有锯齿,跟我设想的无限放大有太大出入,也就是这样做矢量图完全失去了作用,经过一番搜索与试验,发现可以使用这个方法来实现

public void addPath(Path src, Matrix matrix);

然后通过Matrix来缩放。

接下来要解决的就是区域检测了。

经过一番搜索发现有个好东西Region可以用来实现不规则区域检测,但有个问题是区域经过缩放位移操作后跟原来设置的Region已经有出入了,此时还得想办法对坐标进行换算,换算的原理看下图,主要是计算实际地图在原始地图的相对位置即可。

0818b9ca8b590ca3270a3433284dd417.png

到此核心思路和解决办法基本都讲明白了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值