1. 程式人生 > >Android高德地圖之多InfoWindow

Android高德地圖之多InfoWindow

本文是高德地圖系列的最後一文,因為光是寫這幾篇博文,就花去了我一整天時間,什麼也沒做,甚至飯也沒吃,做了一整天,現在身體已經空蕩蕩了,而且最近一段時間工作很忙,每天都很累,所以打算多去鍛鍊身體。有任何疑問也可以留言。

最終效果:生成marker並顯示詳情
這裡寫圖片描述

由於不能上傳2M以上的截圖,只錄了重點,廢話不多講,速度上車。

Marker表示為地圖上的一個點,一個Point,我們可以在這個Marker做各種各樣的操作包括,拖動,獲取地理座標,反編譯地址等等。現在,我們要將Marker新增到地圖上,並達到圖上的效果。

在官方論壇上看到很多人不知道如何實現多InfoWindow的方法,基於此,我決定寫一篇關於實現多Infowindow的曲線救國的方式,按照我這篇文章,我相信你也能做出這種效果。

ok以我的專案為例,需求是在地圖顯示一種裝置的詳情,可以看到裝置ID,型別,次數,經緯度,反地理位置,時間,電量等等。下面是我的實體類BeanEvent 。

private Integer id;
    private String deviceId;
    private String simId;
    private String eventId;
    private String eventType;
    private String eventCount;
    private String latitude;
    private String longitude;
    private
String eventTime; private String actTime; private String battery; private String eventIp; ---此處省略get set方法 // 假資料 public static List<BeanEvent> getEvent() { List<BeanEvent> list = new ArrayList<>(); BeanEvent be1 = new BeanEvent(); be1.
setDeviceId("devid--1111111"); be1.setSimId("simid--1111111"); be1.setEventId("event_1111111"); be1.setEventType("type-1111111"); be1.setEventCount("count_1111111"); be1.setLatitude("39.92746"); be1.setLongitude("116.396481"); be1.setEventTime("20170911"); be1.setBattery("1111111"); be1.setEventIp("1111111"); BeanEvent be2 = new BeanEvent(); be2.setDeviceId("devid--222222"); be2.setSimId("simid--22222"); be2.setEventId("event_22222"); be2.setEventType("type-22222"); be2.setEventCount("count_22222"); be2.setLatitude("39.93746"); be2.setLongitude("116.398681"); be2.setEventTime("20170911"); be2.setBattery("1111111"); be2.setEventIp("1111111"); BeanEvent be3 = new BeanEvent(); be3.setDeviceId("devid--33333"); be3.setSimId("simid--3333"); be3.setEventId("event_33333"); be3.setEventType("type-33333"); be3.setEventCount("count_33333"); be3.setLatitude("39.92956"); be3.setLongitude("116.399541"); be3.setEventTime("20170911"); be3.setBattery("1111111"); be3.setEventIp("1111111"); list.add(be1); list.add(be2); list.add(be3); return list; }

至此,資料來源被模擬出來了。
官方的新增marker的方法

    /**
     * 在地圖上新增marker
     */
    private void addMarkersToMap() {
        markerOption = new MarkerOptions().icon(BitmapDescriptorFactory
                .defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
                .position(latlng)
                .title("標題")
                .snippet("詳細資訊")
                .draggable(true);
        marker = aMap.addMarker(markerOption);
        marker.showInfoWindow();
    }

新增InfoWindow的程式碼我就不演示了,太浪費大家時間,我會直接告訴你,官方程式碼裡的Marker的InfoWindow不支援多個同時顯示,當設定了多個Marker的Infowindow時,只顯示最後一個,這時該怎麼辦呢?

看看我是如何將他們顯示出來的

 ***初始化。。。
 addMarkersToMap(getEvent()); // 新增點
/**
     * 在地圖上新增marker
     */
    private void addMarkersToMap(List<BeanEvent> eventList)
    {
        for (int i = 0; i < eventList.size(); i++)
        {
            BeanEvent be = eventList.get(i);
            markerOption = new MarkerOptions().icon(BitmapDescriptorFactory
                    .fromView(getBitmapView(mActivity, be))).draggable(false);
            markerOption.position(new LatLng(Double.parseDouble(be.getLatitude()), Double.parseDouble(be.getLongitude())));
            marker = aMap.addMarker(markerOption);
            marker.setObject(be);
            markerList.add(marker);
        }
    }

其中,BitmapDescriptorFactory
.fromView(getBitmapView(mActivity, be))方法將返回一個View物件作為Marker的Icon,因此,這裡,我們可以藉助這個方法,實現將Marker與Infowindow結合在一起,即,看起來是marker和Infowindow,實際上,它們整體就是一個Marker。因為marker是多支援多個顯示的,所以這樣的思路是沒有問題的。

其方法是這樣寫的:


    public static View getBitmapView(Context context, BeanEvent be)
    {
        LayoutInflater factory = LayoutInflater.from(context);
        View view = factory.inflate(R.layout.item_marker_title, null);
        TextView tv_title = (TextView) view.findViewById(R.id.tv_title);
        TextView tv_snippet = (TextView) view.findViewById(R.id.tv_snippet);
        tv_title.setText("SIM卡號:" + be.getSimId());
        tv_snippet.setText("公章ID:" + be.getDeviceId());
        return view;
    }

該方法將傳入的物件賦在對應的控制元件上,然後作為View返回。此時的預覽圖為
這裡寫圖片描述
上圖就是我們最終作為marker的icon的圖,屆時,只需要傳入虛擬資料或真實資料,即可顯示出來。

此時多個InfoWindow就實現了。接下來,我們將實現點選marker彈出詳情。

我們先來看一下佈局結構:

<RelativeLayout
                android:id="@+id/rl_info"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_margin="2dp"
                android:animateLayoutChanges="true"
                android:background="@drawable/bg_seal_info"
                android:clickable="true"
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:orientation="vertical"
                android:showDividers="middle"
                android:visibility="gone"
                app:divider="@drawable/iv_devider">

                <TextView
                    android:id="@+id/tv_close"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_alignParentRight="true"
                    android:background="@mipmap/ic_seal"/>

                <LinearLayout
                    android:id="@+id/ll_1"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    android:paddingLeft="10dp"
                    android:paddingRight="10dp"
                    android:paddingTop="10dp">

                    <TextView
                        android:id="@+id/tv_sim"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="卡號:"
                        android:textSize="14sp"/>

                    <TextView
                        android:id="@+id/tv_count"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="次數:"
                        android:textSize="14sp"/>
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/ll_2"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/ll_1"
                    android:orientation="horizontal"
                    android:paddingLeft="10dp"
                    android:paddingRight="10dp"
                    android:paddingTop="5dp">

                    <TextView
                        android:id="@+id/tv_sealNo"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="公章號:"
                        android:textSize="14sp"/>

                    <TextView
                        android:id="@+id/tv_type"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="事件型別:"
                        android:textSize="14sp"/>
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/ll_3"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/ll_2"
                    android:orientation="horizontal"
                    android:paddingLeft="10dp"
                    android:paddingRight="10dp"
                    android:paddingTop="5dp">

                    <TextView
                        android:id="@+id/tv_latitude"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="北緯:"
                        android:textSize="14sp"/>

                    <TextView
                        android:id="@+id/tv_longitude"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="東經:"
                        android:textSize="14sp"/>
                </LinearLayout>

                <TextView
                    android:id="@+id/tv_address"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/ll_3"
                    android:paddingLeft="10dp"
                    android:paddingRight="10dp"
                    android:paddingTop="5dp"
                    android:text="地址:"
                    android:textSize="14sp"/>

                <LinearLayout
                    android:id="@+id/ll_4"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/tv_address"
                    android:orientation="horizontal"
                    android:paddingBottom="10dp"
                    android:paddingLeft="10dp"
                    android:paddingRight="10dp"
                    android:paddingTop="5dp">

                    <TextView
                        android:id="@+id/tv_battery"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="電量:"
                        android:textSize="14sp"/>

                    <TextView
                        android:id="@+id/tv_ip"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="IP:"
                        android:textSize="14sp"/>
                </LinearLayout>

            </RelativeLayout>

效果為:

這裡寫程式碼片

由於詳情中,用到了反地理編譯,即已知經緯度獲取地理位置。
所以我們在Activity中實現以下幾個介面:

 implements GeocodeSearch.OnGeocodeSearchListener, AMap.OnMarkerClickListener

同時,將剛剛的佈局隱藏掉,作為一個介面卡使用:

    public void setInfo(final RelativeLayout rl_layout, Marker marker, RegeocodeResult result)
    {
        ViewHolder viewHolder = null;
        if (rl_layout.getTag() == null)
        {
            viewHolder = new ViewHolder();
            viewHolder.tv_close = (TextView) rl_layout.findViewById(R.id.tv_close);
            viewHolder.tv_sim = (TextView) rl_layout.findViewById(R.id.tv_sim);
            viewHolder.tv_count = (TextView) rl_layout.findViewById(R.id.tv_count);
            viewHolder.tv_sealNo = (TextView) rl_layout.findViewById(R.id.tv_sealNo);
            viewHolder.tv_address = (TextView) rl_layout.findViewById(R.id.tv_address);
            viewHolder.tv_latitude = (TextView) rl_layout.findViewById(R.id.tv_latitude);
            viewHolder.tv_longitude = (TextView) rl_layout.findViewById(R.id.tv_longitude);
            viewHolder.tv_battery = (TextView) rl_layout.findViewById(R.id.tv_battery);
            viewHolder.tv_type = (TextView) rl_layout.findViewById(R.id.tv_type);
            viewHolder.tv_ip = (TextView) rl_layout.findViewById(R.id.tv_ip);
            rl_layout.setTag(viewHolder);
        }
        viewHolder = (ViewHolder) rl_layout.getTag();
        BeanEvent be = (BeanEvent) marker.getObject();
        viewHolder.tv_sim.setText("SIM::" + be.getSimId());
        viewHolder.tv_count.setText("次數:" + be.getEventCount());
        viewHolder.tv_sealNo.setText("公章號:" + be.getDeviceId());
        viewHolder.tv_address.setText(result == null || result.getRegeocodeAddress() == null
                || result.getRegeocodeAddress().getFormatAddress() == null ? "地址:對不起,沒有找到相關地理位置!" : "地址:" + result.getRegeocodeAddress().getFormatAddress() + "附近");
        viewHolder.tv_type.setText("型別:" + be.getEventType());
        viewHolder.tv_latitude.setText("東經:" + be.getLatitude());
        viewHolder.tv_longitude.setText("北緯:" + be.getLongitude());
        viewHolder.tv_battery.setText("電量:" + be.getBattery());
        viewHolder.tv_ip.setText("IP:" + be.getEventIp());

        final ViewHolder finalViewHolder = viewHolder;
        viewHolder.tv_close.setOnClickListener(v ->
        {
            rl_layout.startAnimation(AnimUtils.goneAnim());
            rl_layout.setVisibility(View.GONE);
        });
    }

    class ViewHolder
    {
        TextView tv_address, tv_close, tv_sim, tv_count, tv_sealNo, tv_type, tv_latitude, tv_longitude, tv_battery, tv_ip;
    }

最後,當我們點選,marker的時候,將佈局顯示出來,此處要實現marker的onclicklistener方法:

animMove(aMap, marker.getPosition()); // 帶動畫的移動地圖到marker
        MainActivity.instant.showToast("正在獲取地址資訊...");
        // 發起地理編碼請求
        if (rl_info.getVisibility() == View.VISIBLE) // 如果當前已經有詳情在顯示,先Gone掉
        {
            rl_info.startAnimation(AnimUtils.goneAnim());
            rl_info.setVisibility(View.GONE);
        }
        RegeocodeQuery query = new RegeocodeQuery(convertToLatLonPoint(marker.getPosition()), 200, GeocodeSearch.AMAP);
        geoSearch.getFromLocationAsyn(query);// 設定非同步逆地理編碼請求
        return false;

接下來,在實現地理位置的實現方法:

    @Override
    public void onRegeocodeSearched(RegeocodeResult result, int i)
    {
        if (i == AMapException.CODE_AMAP_SUCCESS)
        {
            setInfo(rl_info, marker, result); // 將結果顯示在marker對應的詳情佈局上
            rl_info.startAnimation(AnimUtils.showAnim());
            rl_info.setVisibility(View.VISIBLE); // 顯示
        } else MainActivity.instant.showToast("獲取地址失敗!請稍後重試!");
    }

    @Override
    public void onGeocodeSearched(GeocodeResult geocodeResult, int i)
    {

    }

這樣,我們就實現了圖上的效果。
最後貼出MapUtils:

 /**
     * 把LatLng物件轉化為LatLonPoint物件
     */
    public static LatLonPoint convertToLatLonPoint(LatLng latlon)
    {
        return new LatLonPoint(latlon.latitude, latlon.longitude);
    }

    /**
     * 把LatLonPoint物件轉化為LatLon物件
     */
    public static LatLng convertToLatLng(LatLonPoint latLonPoint)
    {
        return new LatLng(latLonPoint.getLatitude(), latLonPoint.getLongitude());
    }
/**********************************************************移動地圖**************************************/
    public static void animMove(AMap aMap, LatLng latLng)
    {
        aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
    }

    public static void animMove(AMap aMap, LatLonPoint point)
    {
        aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(convertToLatLng(point), 15));
    }

    public static void animMove(AMap aMap, AMapLocation location)
    {

        aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 18));
    }

至此,該功能已經完全實現。

請支援我,掃描左側二維碼打賞,謝謝。

相關推薦

Android地圖InfoWindow

本文是高德地圖系列的最後一文,因為光是寫這幾篇博文,就花去了我一整天時間,什麼也沒做,甚至飯也沒吃,做了一整天,現在身體已經空蕩蕩了,而且最近一段時間工作很忙,每天都很累,所以打算多去鍛鍊身體。有任何疑問也可以留言。 最終效果:生成marker並顯示詳情

Android地圖基礎

最終效果圖1:選擇日曆選擇日期,其中有下標的日期是有資料的,點選顯示當天地圖上的資料 效果圖2: 生成marker並顯示詳情 由於不能上傳2M以上的截圖,只錄了重點,廢話不多講,速度上車。 - 申請賬號 http://lbs.amap.com

android-------地圖兩點路線和個點路線繪制

分享圖片 下載 style ble use AD tps out font 最近朋友需要兩點路線和多個點路線繪制這個功能,幫忙弄了一下,寫這篇博客與大家分享一下。 兩點路線 是起點和終點兩個經緯度點,高德繪制出路線,可以實現實線和虛線功能 效果圖: 相關屬

Android----地圖個Marker載入網路圖片出現圖片不顯示問題

需求說要地圖上展示的是mark,不是infowindow,加載出網路圖片,由於app的marker比較多,沒有達到需要的效果。 看了看高德地圖api中有這個方法 markerOption.icon(BitmapDescriptorFactory.fromBitmap(Bi

地圖自定義infowindow點選不彈出訊息框

今天在開發過程中,突然產品來了一句地圖上面有要回到以前,再點選Marker的時候需要顯示一個自定義的訊息框,這時候,原本帶著非常陽光的心情上班,結果天氣預報也有不準的時候,我頓時有想搞他的心都有了(之前是他說要去掉這個訊息框),但是作為碼農的我們,當然沒有這個能

android 地圖的接入的demo

    import android.content.Context; import android.content.Intent; import android.graphics.BitmapFactory; import android.graphics.Color;

(六)地圖駕車路線規劃

在專案中用到地圖的地方往往會有導航功能,那麼這一節將介紹一下使用高德地圖來實現駕車路線規劃的功能。 首先來兩張示例圖供參考:                       &nbs

(五)地圖新增groundoverlay覆蓋物

本節主要實現的功能是往地圖上新增一個groundoverlay覆蓋物,用此方式可以實現公園電子導遊,下面先來看一張效果圖吧: 接下來我們還是直接上程式碼: 新建佈局檔案activity_groundoverlay.xml <?xml version="1.0" encod

(四)地圖定位的幾種模式

這一節主要實現的功能是地圖定位的幾種模式,包括展示、定位、追隨、旋轉、旋轉位置、跟隨不移動中心點、旋轉不移動中心點、旋轉位置不移動到中心點,我們根據實際需要來選擇用那種模式。下面還是主要從程式碼中來體現,主要部分有註釋。 還是先新建佈局檔案:activity_locationmodesour

(三)地圖自定義縮放及縮放動畫效果

這一節主要實現的功能是地圖的自定義縮放及縮放的動畫效果,還是直接放上程式碼更直觀些,主要部位裡面基本有註解 還是老樣子,首先是新建activity_zoom_animate.xml佈局檔案 <?xml version="1.0" encoding="utf-8"?> <

(二)地圖手勢互動

上一結主要介紹瞭如何繼承高德地圖,以及地圖的幾種不同的顯示方式,那麼本節我們接著往下看,這一節主要介紹地圖的手勢互動功能,其中包括滑動手勢(地圖是否可以滑動)、縮放手勢(是否可以通過手勢放大縮小地圖)、切斜手勢以及旋轉手勢,另外又加了兩小部分,地圖的單擊、長按、觸控事件,比如點一下獲取地圖上點選

(一)地圖基本屬性以及顯示模式

       我們在開發中常常會用到地圖功能,那麼我們最常用的就是百度地圖和高德地圖了,今天我們就來看一下高德地圖怎麼用,我個人認為高德地圖封裝的還是比較好的,使用起來方便快捷。 首先我們需要到高德開發者平臺註冊賬號,根據API進行操作即可,高德開放平

Android 地圖自定義地圖覆蓋物(Marker)

先上效果圖,攝像頭和攝像頭上的預警事件紅點就是一個自定義佈局作為地圖的marker的圖示。                camera_red.png (素材圖) 官方提供的API參考手冊:http://

android 地圖marker連線

@Override public void getRouteEquipment(final AMap aMap, String signature, String echostr, String timestamp, final Context context, final

Android 地圖新增Marker,Marker點選事件

新增圖片圖示 BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.qidian)); final

地圖顯示個多邊形框

<!--高德地圖開始 --> <script type="text/javascript" src="http://webapi.amap.com/maps?v=1.4.4&key=""你的key"></script> <script src

地圖軌跡回放

最近專案中有需要做車輛的軌跡回放功能,在這裡就給打分享一下還是挺簡單的。 <!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Com

android地圖定位功能的實現

<1>先去高德開放平臺去申請開發者賬號,並且建立應用,獲取API Key <2>在清單檔案中配置key,其中value是應用的key值 <meta-data android:name="com.amap

Android——地圖設定中心點和縮放比例,獲取兩點之間距離

/** * 監聽amap地圖載入成功事件回撥 */ @Override public void onMapLoaded() { LatLng marker1 = new LatLng(39.90403, 116.407525);

Android地圖使用

在Swift基礎 - - 高德地圖實踐(一)中使用swift來使用高德地圖,這裡使用Android實踐高德地圖包含定位,移動地圖動畫,獲取網路資料,marker標記以及點選,Infowindow自定義介面以及點選,以及點選無marker地圖上面隱藏infowindow等功能。