Google Map API v2 (三)----- 地图上添加标记(Marker),标记info窗口,即指定经纬度获取地址字符串...
接上篇 http://www.cnblogs.com/inkheart0124/p/3536322.html
1,在地图上打个标记
1 private MarkerOptions mMarkOption; 2 3 mMarkOption = new MarkerOptions().icon(BitmapDescriptorFactory.fromAsset("target.png")); 4 mMarkOption.draggable(true); 5 6 double dLat = mLocation.getLatitude(); 7 double dLong = mLocation.getLongitude(); 8 9 LatLng latlng = new LatLng(dLat, dLong); 10 11 mMarkOption.position(latlng); 12 mMarkOption.title("title"); 13 mMarkOption.snippet("snippet"); 14 Marker mMarker = mMapView.addMarker(mMarkOption);
3行,MarkerOptions对象,自己设置一个icon( target.png)
4行,设置为可拖动
6~9行,构造当前经纬度的LatLng
11~13行,设置标记的位置,info window的标题title、详细snippet
14行,GoogleMap的 addMarker(MarkerOptions) 方法,把标记添加到地图上,返回Marker对象mMarker。
2,拖动标记
设置标记可拖动:
方法一、先设置mMarkOption.draggable(true);,再addMarker;
方法二、Marker的setDraggable(boolean)方法;
Google Map 默认长按标记开始拖动,开发者只需要注册监听。注册拖动事件监听
mMapView.setOnMarkerDragListener(this);
acitiviy实现OnMarkerDragListener接口如下:
1 /* OnMarkerDragListener start */ 2 @Override 3 public void onMarkerDrag(Marker marker) { 4 } 5 6 @Override 7 public void onMarkerDragEnd(Marker marker) { 8 } 9 10 @Override 11 public void onMarkerDragStart(Marker marker) { 12 if(marker.isInfoWindowShown()) 13 marker.hideInfoWindow(); 14 mMarkerLoaded = false; 15 } 16 /* OnMarkerDragListener end */
3行,public void onMarkerDrag(Marker marker),当Marker拖动的过程中会不断调用此函数,拖动中marker的位置marker.getPosition()可以得到经纬度。
7行,public void onMarkerDragEnd(Marker marker),拖动结束
11行,public void onMarkerDragStart(Marker marker),开始拖动
11~15行,开始拖动的时候,判断如果正在显示info window,则隐藏info window。
3,点击标记弹出info window
点击marker的default动作就是显示info window,之前设置的title和snippet会显示在infowindow中。
我们对info window做一点小改造,让他显示一个小图标和标记地点的地址
代码:
activity 实现InfoWindowAdapter接口(implements InfoWindowAdapter)
调用GoogleMap的方法setInfoWindowAdapter()方法
mMapView.setInfoWindowAdapter(this);
activity中实现InfoWindowAdapter的两个方法:
public View getInfoWindow(Marker marker);返回的View将用于构造整个info window的窗口
public View getInfoContents(Marker marker);返回的View将用于构造info window的显示内容,保留原来的窗口背景和框架
首先需要定义一个View的布局
res/layout/map_info.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 3 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="wrap_content" 5 android:layout_height="wrap_content" 6 > 7 8 <ImageView 9 android:id="@+id/map_info_image" 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 android:layout_alignParentLeft="true" 13 android:layout_marginLeft="0dip" 14 android:layout_marginTop="0dip" 15 /> 16 17 <LinearLayout 18 android:layout_toRightOf="@id/map_info_image" 19 android:layout_width="200dip" 20 android:layout_height="wrap_content" 21 android:layout_marginLeft="5dip" 22 android:layout_marginTop="0dip" 23 android:orientation="vertical" 24 > 25 <TextView 26 android:id="@+id/map_info_title" 27 android:layout_width="wrap_content" 28 android:layout_height="wrap_content" 29 android:text="map_info_title" 30 android:layout_gravity="center" 31 /> 32 33 <TextView 34 android:id="@+id/map_info_snippet" 35 android:layout_width="wrap_content" 36 android:layout_height="wrap_content" 37 android:text="map_info_snippet" 38 android:layout_gravity="center" 39 /> 40 41 </LinearLayout> 42 43 </RelativeLayout>
实现getInfoContents函数:
1 /* GoogleMap.InfoWindowAdapter begin */ 2 private View mInfoWindowContent = null; 3 @Override 4 public View getInfoContents(Marker marker) { 5 6 if(mInfoWindowContent == null){ 7 mInfoWindowContent = mInflater.inflate(R.layout.map_info, null); 8 } 9 10 ImageView infoImage = (ImageView)mInfoWindowContent.findViewById(R.id.map_info_image); 11 infoImage.setImageResource(R.drawable.address); 12 TextView infoTitle = (TextView)mInfoWindowContent.findViewById(R.id.map_info_title); 13 infoTitle.setText(marker.getTitle()); 14 15 TextView infoSnippet = (TextView)mInfoWindowContent.findViewById(R.id.map_info_snippet); 16 infoSnippet.setText(marker.getSnippet()); 17 return mInfoWindowContent; 18 } 19 20 @Override 21 public View getInfoWindow(Marker marker) { 22 return null; 23 }
6~8行,根据布局文件 res/layout/map_info.xml 填充一个View的布局
LayoutInflater mInflater = LayoutInflater.from(this); //this即activity的context
10~11行,设置图标
12~13行,设置title,marker.getTitle()取出marker中保存的title字符串
15~16行,设置snippet,marker.getSnippet()取出marker的snippet字符串
当点击标记弹出info window时,首先会跑到getInfoWindow(),如果返回null,就会跑到getInfoContents(),返回的View就显示到info window中。
4,根据经纬度发查地址,用snippet字段显示地址信息
首先监听marker点击事件
mMapView.setOnMarkerClickListener(this);
activity实现OnMarkerClickListener接口:
/* OnMarkerClickListener start */ @Override public boolean onMarkerClick(Marker marker) {if(mMarkerLoaded == false)getAddressOfMarker();return false; } /* OnMarkerClickListener end */
即,点击marker,在弹出info窗口前先去查询marker所在的经纬度的地理地址。
这个函数要返回false。如果返回true,则表示click事件被消费掉了,就不会再触发默认动作(即弹出info窗口)。
看下google的geocoder反解地址的过程:
private GetAddressTask mGetAddTack = null;private void getAddressOfMarker(){ if(mGetAddTack != null){mGetAddTack.cancel(true);}mGetAddTack = new GetAddressTask(this);mGetAddTack.execute(mCarMarker.getPosition()); }
getAddressOfMarker函数中执行了一个异步小任务GetAddressTask,代码如下:
1 private class GetAddressTask extends AsyncTask<LatLng, Void, String[]>{ 2 Context mContext; 3 4 public GetAddressTask(Context context) { 5 super(); 6 mContext = context; 7 } 8 9 @Override 10 protected void onPreExecute(){ 11 mMarker.setTitle(getResources().getString(R.string.mapAddrLoading)); 12 mMarker.setSnippet(" "); 13 if(mMarker.isInfoWindowShown()) 14 mMarker.showInfoWindow(); 15 } 16 17 @Override 18 protected void onPostExecute(String[] result){ 19 if(result == null) 20 return; 21 22 if(mMarker != null){ 23 if((result[1] != null) && (result[0] != null)){ 24 mMarker.setTitle(result[0]); 25 mMarker.setSnippet(result[1]); 26 if(mMarker.isInfoWindowShown()) 27 mMarker.showInfoWindow(); 28 } 29 else{ 30 mMarker.setTitle(getResources().getString(R.string.mapAddrTitle)); 31 mMarker.setSnippet(getResources().getString(R.string.mapAddrUnknown)); 32 if(mMarker.isInfoWindowShown()) 33 mMarker.showInfoWindow(); 34 }35 } 36 } 37 mMarkerLoaded = true; 38 } 39 40 @Override 41 protected String[] doInBackground(LatLng... params) { 42 LatLng latlng = params[0]; 43 String[] result = new String[2]; 44 45 String urlString = "http://maps.google.com/maps/api/geocode/xml?language=zh-CN&sensor=true&latlng=";//31.1601,121.3962"; 46 HttpGet httpGet = new HttpGet(urlString + latlng.latitude + "," + latlng.longitude); 47 HttpClient httpClient = new DefaultHttpClient(); 48 49 InputStream inputStream = null; 50 HttpResponse mHttpResponse = null; 51 HttpEntity mHttpEntity = null; 52 try{ 53 mHttpResponse = httpClient.execute(httpGet); 54 mHttpEntity = mHttpResponse.getEntity(); 55 inputStream = mHttpEntity.getContent(); 56 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 57 58 String line = ""; 59 String startTag = "<formatted_address>"; 60 String endTag = "</formatted_address>"; 61 while (null != (line = bufferedReader.readLine())){ 62 if(isCancelled()) 63 break; 64 line = line.trim(); 65 String low = line.toLowerCase(Locale.getDefault()); 66 if(low.startsWith(startTag)){ 67 int endIndex = low.indexOf(endTag); 68 String addr = line.substring(startTag.length(), endIndex); 69 if((addr != null) && (addr.length() >0)){ 70 result[1] = addr; 71 result[0] = getResources().getString(R.string.mapAddrTitle); 72 break; 73 } 74 } 75 } 76 } 77 catch (Exception e){ 78 log("Exception in GetAddressTask doInBackground():" + e); 79 } 80 finally{ 81 try{ 82 if(inputStream != null) 83 inputStream.close(); 84 } 85 catch (IOException e){ 86 log("IOException in GetAddressTask doInBackground():" + e); 87 } 88 } 89 return result; 90 } 91 }
重点是41行开始的 doInBackground 函数,向google的geocoder发起一个http请求,请求格式如下:
http://maps.google.com/maps/api/geocode/xml?language=zh-CN&sensor=true&latlng=30.1601,121.3922
返回数据可以是JSON或XML,我这里用的是XML,语言中文zh-CN,latlng=纬度,经度
返回的XML脚本,是指定经纬度附近的有效地址,可能不只一个。我们只取第一个<formatted_address></formatted_address>标签中的字符串,保存在result中。
18行,在任务执行结束的onPostExcute函数中,调用marker.setSnippet(result[1])保存到snippet中,title则根据任务执行情况设置成合适的String。
26~28行,由于这是一个异步任务,地址取回的时候,info窗口可能已经显示出来了,这时调用showInfoWindow(),getInfoContents函数会重新跑一次,让窗口显示最新取到的title和snippet。
转载于:https://www.cnblogs.com/inkheart0124/p/3536848.html
Google Map API v2 (三)----- 地图上添加标记(Marker),标记info窗口,即指定经纬度获取地址字符串...相关推荐
- 关于Google Map API V2 版本的定位与导航
近来,在关注安卓手机上的GoogleMap应用的开发,但是目前官方API版本网页版已经升级到V3版,而对于Android的支持也已经升级到V2版本,虽然Google说继续对V1版提供服务,但是不再提供 ...
- Google Map API v2的定位
昨天刚开始看LBS相关的东西,搜了下发现几个问题:一个是时效性的问题,很多发表时间还算近的 内容写的却是V1的,很容易让我们这些菜鸟走更多的弯路:另一个是知识面的,发现有太多太多相同的文章 都在写一个 ...
- 主流电子地图API比较 google map api, mapabc ,yahoo地图
主流电子地图API比较 Google Maps API : Google Maps API 基于Google Maps,能够使用 JavaScript 将 Google Maps 嵌入网页中.API ...
- Google Map API v2 步步为营 (二)----- Location
接上篇. 改造一下MapsActivity: public class MapsActivity extends Activity implements LocationListener, InfoW ...
- android Google Map API V2 (key 申请)
要使用V2 的API,需要到Google APIs Console将Google Maps Android API v2服务开启(前提是你已经拥有Google帐号,并创建一个项目),见图: 然后用ke ...
- Google Map API使用谷歌地图api实现地点搜索功能
需求:提供谷歌地图搜索地点功能,并查出经纬度坐标. 官方文档:https://developers.google.com/maps/?hl=zh-cn 地点详情接口: https://maps.goo ...
- Google Map API 学习三
转载于:https://www.cnblogs.com/MyFlora/p/3154066.html
- GIS(二)——在js版搜狗地图上添加brand标牌
在上一篇博文中,我在搜狗地图上添加了Marker标记,但是在用户体验度上还是不够的,如果想了解某些信息,你得把鼠标指向marker,才能看到title里的值.有没有一种可以直接显示在marker上的东 ...
- Google Map API 使用总结
Google Map API (一):显示一个最基本的地图 1 实现一个地图: <head>中引用: <script type="text/javascript" ...
最新文章
- 哥德尔90年前的「不完备性定理」,奠定了计算机与AI的理论基础
- 【自学笔记】定义一个标准的WPF窗口
- 织梦最新版后台一键更新网站、更新文档HTML卡死的解决方法
- 教你玩转CSS 组合选择符
- centos的yum源换成阿里云
- 软件工程(2018)第四次团队作业
- 关于4A系统(我对4A系统的维护的理解)
- python dll load fail_python报错DLL load failed:找不到模块怎么解决?
- 使用 Docker Machine 添加机器记录
- iptables 报错 MASQUERADE':No such file or directory
- Centos7.2修复yum
- L18-python语法基础-数据类型的基本操作(d5)
- cv2 在图片上画线
- threejs 加载两个场景_three.js 场景切换
- MVP、EMC、CRM、IoT、边缘计算盒子、系统群控、数字化赋能、EMS、冷媒
- 试题 入门训练 Fibonacci数列
- 优麒麟 配置java_优麒麟中安装虚拟机(ARM64)
- 一分钟教你如何使用edge浏览器玩4399小游戏
- Python必学基础
- ERP项目应该由谁来主导?
热门文章
- 齐齐哈尔计算机二级,2020齐齐哈尔市计算机二级报名时间|网上报名入口【8月20日9时开通】...
- PHP调用类函数定义位置,OOP PHP – 如何有选择地调用类的构造函数中定义的特定方法?...
- terminal显示mysql_mac如何在terminal终端中操作mysql
- python输入n×n的矩阵_Python使用shape计算矩阵的行和列
- 7z001怎么解压在安卓手机上面_安卓手机怎么设置网易企业邮箱
- 纯新手DSP编程--5.15--CCS简述
- 2012.4.19总结(一)
- 里式替换(LSP)跟多态有何区别?
- docker pull命令入门
- Spark序列化入门