• 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。

  • 相关阅读:
    个人冲刺6
    个人冲刺5
    个人冲刺4
    学习进度10
    个人冲刺3
    个人冲刺2
    单词统计
    返回一个整数数组中最大子数组的和
    JavaWeb_JavaEE_命名规则 转载http://www.cnblogs.com/xwdreamer/
    软件工程作业(四则运算web界面实现)-3
  • 原文地址:https://www.cnblogs.com/inkheart0124/p/3536848.html
Copyright © 2020-2023  润新知