高德API使用小結(jié)-定位和marker

功能描述:實(shí)現(xiàn)一個普通的地圖展示党觅,地圖上有當(dāng)前定位小藍(lán)點(diǎn)和門店定位Marker信息术荤。當(dāng)前定位需要從定位服務(wù)異步獲取倚喂,可能失敗,門店的位置從接口異步獲取,兩個異步的數(shù)據(jù)最終展示在一個地圖View上端圈,并且Marker需要展示info window焦读,需要兩者不重疊不遮擋完全展示。

效果如下圖:


需求.png

接入準(zhǔn)備:

1舱权、下載jar包(如Android_Map3D_SDK_V5.2.1_20170630.jar)矗晃,放入工程libs目錄。
2宴倍、build.gradle文件添加:
compile 'com.amap.api:3dmap:latest.integration'
3张症、添加meta-date,appkey信息鸵贬。
4俗他、添加地圖需要的權(quán)限,如定位等阔逼。

使用步驟:

xml中添加布局:
<com.amap.api.maps.MapView
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:layout_marginTop="30dp" />

SDK底層使用OpenGL ES實(shí)現(xiàn)了兩個地圖組件兆衅,分別是GLSurfaceView、TextureView嗜浮。

特點(diǎn):
1羡亩、GLSurfaceView
包括 MapView、MapFragment危融、SupportMapFragment 三種容器畏铆。下面簡單介紹一下 SupportMapFragment:
MapFragment 是 Android Fragment 類的一個子類,用于在 Android Fragment 中放置地圖吉殃。 MapFragment 也是地圖容器辞居,與 MapView 一樣提供對 AMap 對象(地圖的控制類)的訪問權(quán)。與 MapView 相比 SupportMapFragment 方便之處在于其可以更好的管理地圖的生命周期寨腔,布局靈活速侈。
2、TextureView
包括TextureMapView迫卢、TextureMapFragment、TextureSupportMapFragment 三種容器冶共。
使用場景:您將MapView與其他的GLSurfaceView(比如相機(jī))疊加展示乾蛤,或者是在ScrollView中加載地圖時,建議使用TextureMapView及SupportTextureMapFragment來展示地圖捅僵,可以有效解決 GLSurfaceView 疊加時出現(xiàn)的穿透家卖、滾動黑屏等問題。

根據(jù)需求合理選擇實(shí)現(xiàn)的組件和方式

初始化MapView和管理對象AMap庙楚,顯示地圖
MapView mMapView.onCreate(savedInstanceState);
aMap = mMapView.getMap();

// info window的適配器
aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
    @Override
    public View getInfoWindow(Marker marker) {
       return null;
    }
    @Override
    public View getInfoContents(Marker marker) {
        return null;
    }
}

// 搞一些marker上荡,然后給marker設(shè)置info window,這個過程由aMap來完成
Marker maker = aMap.addMarker(new MarkerOptions()
                .icon(BitmapDescriptorFactory.fromBitmap(
                        BitmapFactory.decodeResource(getResources(), R.drawable.xxx)))
                .title("title")
                .snippet("xxx")
                .anchor(0.5F, 0.5F)
                .position(storeLatLng)
                .draggable(false)
                .setFlat(true));


// 設(shè)置地圖的UI屬性
UiSettings uiSettings = aMap.getUiSettings();
// 隱藏縮放控件
uiSettings.setZoomControlsEnabled(false);
// 隱藏比例尺控件
uiSettings.setScaleControlsEnabled(false);
...

// 設(shè)置事件交互
aMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
    @Override
    public boolean onMarkerClick(Marker marker) {
        // 消耗事件,不繼續(xù)傳遞
        return true;
    }
});
aMap.setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
    @Override
    public void onInfoWindowClick(Marker marker) {
        // 點(diǎn)擊打開導(dǎo)航dialog
        ToastUtil.showShortMsg(XXX.this, "打開導(dǎo)航dialog");
    }
});

// 開始定位酪捡,并顯示定位小藍(lán)點(diǎn)
final MyLocationStyle myLocationStyle = new MyLocationStyle();
// 設(shè)置自定義小藍(lán)點(diǎn)的圖標(biāo)
myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.mylocation));
// 設(shè)置小藍(lán)點(diǎn)的錨點(diǎn)
myLocationStyle.anchor(0.5F, 0.5F);
// 設(shè)置小藍(lán)點(diǎn)的邊框顏色
myLocationStyle.strokeColor(getResources().getColor(R.color.blue));
// 設(shè)置小藍(lán)點(diǎn)的填充顏色
myLocationStyle.radiusFillColor(Color.argb(100, 29, 161, 242));
// 設(shè)置小藍(lán)點(diǎn)的邊框粗細(xì)
myLocationStyle.strokeWidth(1.0F);
// 表示地圖只定位一次
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
// 是否顯示定位小藍(lán)點(diǎn)
myLocationStyle.showMyLocation(true);
aMap.setMyLocationStyle(myLocationStyle);

// 高德api在5.0對定位的實(shí)現(xiàn)做了更改叁征,官網(wǎng)(https://lbs.amap.com/api/android-sdk/guide/create-map/mylocation)
aMap.setOnMyLocationChangeListener(new AMap.OnMyLocationChangeListener() {
    @Override
    public void onMyLocationChange(Location location) {
        // 從location對象中獲取經(jīng)緯度信息,地址描述信息逛薇,建議拿到位置之后調(diào)用逆地理編碼接口獲绒嗵邸(獲取地址描述數(shù)據(jù)章節(jié)有介紹)
        if (location != null) {
            locationLatLng = new LatLng(location.getLatitude(), location.getLongitude());
            if (storeLatLng != null) {
                zoomToSpanWithCenter();
            }
        }
    }
});

// 設(shè)置為true表示啟動顯示定位小藍(lán)點(diǎn),false表示隱藏定位小藍(lán)點(diǎn)并不進(jìn)行定位永罚,默認(rèn)是false啤呼。
aMap.setMyLocationEnabled(true);

現(xiàn)在地圖就可以正常展示了,定位完成后呢袱,會顯示定位小藍(lán)點(diǎn)官扣,我們設(shè)置為只定位一次,這樣可以節(jié)省性能和電量羞福,并且也符合需求醇锚。

還有一些問題:
1、高德地圖縮放級別分為大概20級坯临,我們需要顯示一個合適的級別焊唬。
2、我們給marker設(shè)置的info window會出現(xiàn)被遮擋的情況看靠。

接下來對地圖做進(jìn)一步的約束

1赶促、縮放到合適的級別:
LatLngBounds.Builder這個api可以幫助我們獲取最佳的展示縮放比例,我們需要指定一個中心點(diǎn)挟炬,另外在傳入一些我們需要展示的經(jīng)緯度的集合鸥滨,然后它會返給我們一個存儲有合適范圍約束的LatLngBounds對象。

private LatLngBounds getLatLngBounds(LatLng centerPoint, List<LatLng> pointList) {
    LatLngBounds.Builder builder = LatLngBounds.builder();
    if (centerPoint != null) {
        for (int i = 0; i < pointList.size(); i++) {
            LatLng p = pointList.get(i);
            LatLng p1 = new LatLng((centerPoint.latitude * 2) - p.latitude,
                    (centerPoint.longitude * 2) - p.longitude);
            builder.include(p);
            builder.include(p1);
        }
    }
    return builder.build();
}

有了合適范圍約束對象后谤祖,我們的marker和當(dāng)前位置小藍(lán)點(diǎn)都可以展示在地圖里婿滓,需要我們調(diào)整一下地圖的顯示

LatLngBounds bounds = getLatLngBounds(centerLatLng, pointList);
// 第二個參數(shù)為地圖設(shè)置padding
aMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));

設(shè)置好padding,防止顯示的marker等離地圖范圍邊挨得太近粥喜。

2凸主、info window被遮擋,顯示不全的問題
在一番搜索之后额湘,發(fā)現(xiàn)并沒有合適的api可以使用卿吐,┭┮﹏┭┮
突然想到是不是可以添加一些不顯示的點(diǎn)來重新讓地圖定位,用這些不可見的點(diǎn)來把我們要顯示的內(nèi)容給圈起來锋华,圈定一個范圍嗡官。

相對于定位的小藍(lán)點(diǎn),門店的點(diǎn)有四個相對的位置毯焕,如下圖:


圖1.png

圖2.png

圖3.png

圖4.png

其中衍腥,圖2和圖3容易被遮擋,我們在這兩個位置的上方和右方添加兩個點(diǎn)就可以顯示我們的需求

public void zoomToSpanWithCenter() {
    List<LatLng> pointList = new ArrayList<>();
    LatLng centerLatLng;
    LatLng helperLatLngVertical = null;
    LatLng helperLatLngHorizontal = null;

    // 判斷店鋪和當(dāng)前位置哪個緯度更高,然后添加輔助點(diǎn)以更好地分配位置防止店鋪info window顯示不全
    if (storeLatLng.latitude > locationLatLng.latitude) {
        helperLatLngVertical = new LatLng(Math.max(storeLatLng.latitude, locationLatLng.latitude)
                + Math.abs(storeLatLng.latitude - locationLatLng.latitude), storeLatLng.longitude);
    }
    // 判斷店鋪和當(dāng)前位置哪個經(jīng)度更靠右側(cè)婆咸,然后添加輔助點(diǎn)以更好地分配位置防止店鋪info window顯示不全
    if (storeLatLng.longitude > locationLatLng.longitude) {
        helperLatLngHorizontal = new LatLng(storeLatLng.latitude,
                Math.max(storeLatLng.longitude, locationLatLng.longitude)
                + Math.abs(storeLatLng.longitude - locationLatLng.longitude) / 10);
    }

    pointList.add(storeLatLng);
    pointList.add(locationLatLng);
    if (helperLatLngVertical != null) {
        pointList.add(helperLatLngVertical);
    }
    if (helperLatLngHorizontal != null) {
        pointList.add(helperLatLngHorizontal);
    }
    centerLatLng = new LatLng((locationLatLng.latitude + storeLatLng.latitude
            + (helperLatLngVertical != null ? helperLatLngVertical.latitude : 0)
            + (helperLatLngHorizontal != null ? helperLatLngHorizontal.latitude:0)) / pointList.size(),
            (locationLatLng.longitude + storeLatLng.longitude
                    + (helperLatLngVertical != null ? helperLatLngVertical.longitude : 0)
                    + (helperLatLngHorizontal != null ? helperLatLngHorizontal.longitude:0)) / pointList.size());

    LatLngBounds bounds = getLatLngBounds(centerLatLng, pointList);
    // 第二個參數(shù)為地圖設(shè)置padding
    aMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
}

最終顯示不會被遮擋竹捉,并且縮放顯示也合乎要求,O(∩_∩)O

掃尾工作:

1擅耽、檢查有沒有泄露情況活孩、該釋放的資源有沒有及時釋放

@Override
protected void onDestroy() {
    super.onDestroy();
    mMapViewStoreDetail.onDestroy();
    if (mLocationClient != null) {
        mLocationClient.onDestroy();
    }
}

在Android Studio里打開Android Profiler查看打開、關(guān)閉activity情況下實(shí)例有沒有及時回收釋放乖仇。
2憾儒、有沒有

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市乃沙,隨后出現(xiàn)的幾起案子起趾,更是在濱河造成了極大的恐慌,老刑警劉巖警儒,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件训裆,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜀铲,警方通過查閱死者的電腦和手機(jī)边琉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來记劝,“玉大人变姨,你說我怎么就攤上這事⊙岢螅” “怎么了定欧?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長怒竿。 經(jīng)常有香客問我砍鸠,道長,這世上最難降的妖魔是什么耕驰? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任爷辱,我火速辦了婚禮,結(jié)果婚禮上耍属,老公的妹妹穿的比我還像新娘托嚣。我一直安慰自己,他們只是感情好厚骗,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著兢哭,像睡著了一般领舰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天冲秽,我揣著相機(jī)與錄音舍咖,去河邊找鬼。 笑死锉桑,一個胖子當(dāng)著我的面吹牛排霉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播民轴,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼攻柠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了后裸?” 一聲冷哼從身側(cè)響起瑰钮,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎微驶,沒想到半個月后浪谴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡因苹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年苟耻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扶檐。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡凶杖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蘸秘,到底是詐尸還是另有隱情官卡,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布醋虏,位于F島的核電站寻咒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏颈嚼。R本人自食惡果不足惜毛秘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阻课。 院中可真熱鬧叫挟,春花似錦、人聲如沸限煞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽署驻。三九已至奋献,卻和暖如春健霹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瓶蚂。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工糖埋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窃这。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓瞳别,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杭攻。 傳聞我的和親對象是個殘疾皇子祟敛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容