Android自定义导览地图组件(二)

原创 cheny  2017-10-17 22:05  评论 0 条

版权说明 : Android自定义导览地图组件(二)于当前乘月网CSDN博客属同一原创,转载请说明出处,谢谢。

 

前段时间一直忙碌加上难得的8天假直至今日才得以调整,向大家表以歉意。上一篇《Android自定义导览地图组件(一)》主要讲述了导览地图的概览,实现思路以及大图浏览“MapView”的实现,本篇围绕“地图坐标“的实现展开叙述,完成整体导览地图功能,下面继续:

   二、定位图标Marker

一个marker需要哪些元素?

1.作为图片显示的载体,ImageView肯定是家中必备良品;
2.哦对,图片呢?OK,配上小图标资源id;
3.显示在哪啊?给个X、Y坐标呗。 ↓↓↓↓↓↓↓↓↓↓↓下方高能,如有不适,也要看完。。。

嗯哼,理论上是这样的,这里是以图片像素点作为坐标,比如一张240*320分辨率的图片(地图),左上角为原点,那么marker在图片上的显示坐标范围就是(0,0)到(240,320)。由于地图是可缩放的,图片的分辨率会发生变化,marker坐标也需要动态调整,显然不能取固定值,于是坐标比例方案孕育而生,以上面提到的图片为例:要显示一个坐标为(60,240)的marker,其坐标比例scaleX=60*1f/240=0.25,scaleY=240*1f/320=0.75,如果图片放大2倍(分辨率为480*640)时,marker坐标需变为(480*scaleX,640* scaleY)即(120,480),下面为示意图:

OK,这样就可以建起一个Marker实体类,代码如下:

三、给导览地图配置初始化属性map_attr.xml.xml

直接看xml代码:

顾名思义,分别是marker(定位图标)显示的宽、高和下落动画时间属性,具体怎么用,下文见晓。

四、自定义MapContainer

先看代码:

自定义ViewGroup为MapContainer类,构造方法中获取配置参数并初始化marker需要显示的宽、高和下落动画时间的值。这里MapContainer仅仅作为承载地图和marker的容器(父View)以及作为MapView与maker们的沟通桥梁,没有onMeasure和onLayout什么事,只作了简单的实现,关于“isFirstLayout”这个flag的注释一定要好好看看。

好了,终于可以让小marker们上场了,先看代码:

开放setMarkers()方法便于传入marker数据,每次传入的时候移除已显示的marker(要不要移除看需求),接下来initMarkers()方法是对markers初始化赋值以及为业务类(OnMarkerClickListner或其实现类)绑定marker点击事件。
上述代码提到了R.id.is_marker,这个资源为values文件下新建的map_ids.xml文件,其代码如下:

OK,继续折腾,在MapContainer构造方法里完成MapView的初始化创建,考虑到一般地图都是动态从后台API获取的,所以开放了getMapView()方法给相关业务类获取MapView对象以便于加载本地或网络图片,看代码:

下面分析下导览地图一开始显示过程中所需的代码设计流程:

  1.地图(图片)加载 ----> 2.地图加载完成后计算自适应屏幕缩放比例 ----> 3.地图自适应屏幕显示 ----> 4.markers计算坐标并显示 ----> 5.markers执行下落动画

OK,着重说说流程4,其代码执行是在流程3后,这不是废话么?呜呜~~,只是强调下嘛,流程3执行完后告知流程4:XXX歌星(地图)已经画好妆上台表演了,我把它最新的方位(尺寸和坐标)告诉你,你可以拿去参考下找准配角们(markers)的出场位置后喊他们去表演吧。嗯哼,还是说了一大堆废话,就只是强调那个告知的接口方法onChanged (RectF rectF),rectF便是尺寸和坐标喽。

下面再分析下导览地图操作场景中所需的代码设计流程:
场景一:1.地图移动 ----> 2.markers计算坐标并显示
场景二:1.地图缩放 ----> 2.markers计算坐标并显示
场景三:1.地图同时缩放并移动 ----> 2.markers计算坐标并显示

OK,场景三直接忽略吧,同时调用场景一和场景二的接口方法就得了。你还在想场景一的解决方案是地图朝哪个方向移动n距离,marker就跟着移动n距离吗?还在想场景二的解决方案是根据缩放点(上一篇文章提到的getFocusX,getFocusY)计算偏移方向和距离决定marker的坐标吗?需要两个对应的接口方法?恩,是可以实现,不过这条路走得可真是迂回婉转。
其实只需要上文提到的onChanged (RectF rectF)就够啦!Excuse Me?又是它?就是这么简单,你(地图)移动和缩放跟我(marker)有半毛钱关系?你只要在移动和缩放的时候告诉我你最新的尺寸和坐标,我自己计算自己的坐标不就好了咩!说了那么多,是不是很期待这个onChanged()了呢?上代码:

MapView.java里的代码:

代码注释得很详细,不作赘述了。

上文提到接口OnMapStateChangedListner下的方法onChanged(RectF rectF)触发场景,即:自适应屏幕缩放、手势移动以及缩放的状态变化,那么只要在MapView.java里会发生变化的代码处----setImageMatrix( matrix ) 补上"onChangedListner.onChanged( rectF )"即可:

好了,写个Demo测试下效果,MainActivity.java:

布局文件activity_main.xml:

效果如下:

恩~~  效果还不错,终于结束了这场写博之路,坎坷,漫长。。。

下载源码:《Android自定义导览地图组件_GuideMap》,GitHub下载地址:https://github.com/ausboyue/GuideMap

结束了!结束了!结束了!欢迎童鞋们留言提问,给出宝贵的意见,博客和源码会不定期更新~~

本文地址:http://icheny.cn/android%e8%87%aa%e5%ae%9a%e4%b9%89%e5%af%bc%e8%a7%88%e5%9c%b0%e5%9b%be%e7%bb%84%e4%bb%b6%e4%ba%8c/
关注我们:加我微信:扫描二维码乘月网的微信号,微信号:ausboyue
版权声明:本文为原创文章,版权归 cheny 所有,欢迎分享本文,转载请保留出处!

发表评论


表情