關於Android集成高德地圖的那些事兒...地圖標註Marker 、Poi 搜索

    上一篇博客介紹了地圖的顯示,不要太簡單了, 我們要實現的效果當然不僅僅是顯示地圖這麼廢了, 現在地圖是有了 , 怎麼在地圖上添加一個標註呢? 添加一個圓形?又或者是我想在地圖上添加個自定義的View, 會不會很6? 呵呵 

    答案全在AMap aMap=mapView.getMap(); 我們添加的這些東西都是要在aMap上操作的 , 之前有說道定位回調的方法裏面顯示了系統的定位小藍點 ,  那我不想要那個效果咋整 ? 當然了SDK中的api可以修改定位點的樣式 , 這個就不說了 , 對於強迫症的我來說 , 不如自己搞一個來的痛快, 系統定位藍點不過就是個Marker而已

    先來創建一個Marker ,  aMap.addMarker( ) 方法返回值就是Marker對象 , 方法參數接收的是 MarkerOptions  ; MarkerOptions 可以設置資源圖片 , 設置錨點 ,標題等等 ;重點說下這個圖片MarkerOptions有個icon()方法 可以加載資源圖片 , 也可以加載自定義View ; 有趣的是 ,api現在已經支持給Marker添加動畫了  , 那就在添加Marker的同時 加入縮放和透明度漸變的動畫

// BitmapDescriptorFactory.fromView(View view);
// BitmapDescriptorFactory.fromBitmap(Bitmap bitmap)
// BitmapDescriptorFactory.fromAsset(String s);
// BitmapDescriptorFactory.fromResource(int res);
// BitmapDescriptorFactory.fromFile(String path);

//加載一個layout
View view = View.inflate(this, R.layout.item_marker, null);
((TextView) view.findViewById(R.id.num)).setText("layout");
Marker addMarker = aMap.addMarker(new MarkerOptions()
                       .icon(BitmapDescriptorFactory.fromView(view))
                       .position(new LatLng(locationInfo.getLatitude(), locationInfo.getLongitude())));

//Marker 開啓動畫
private void startAnimation(Marker marker) {
        AnimationSet animationSet = new AnimationSet(false);
        Animation scale = new ScaleAnimation(0, 1, 0, 1);
        Animation alpha = new AlphaAnimation(0, 1);
        animationSet.addAnimation(alpha);
        animationSet.addAnimation(scale);
        animationSet.setDuration(300);
        animationSet.setInterpolator(new LinearInterpolator());
        marker.setAnimation(animationSet);
        marker.startAnimation();
    }


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/ic_location_blue_small" />

    <TextView
        android:id="@+id/num"
        style="@style/text_10_color_1_style"
        android:layout_gravity="center"
        android:layout_marginBottom="6dp"
        android:text="5"
        android:textStyle="bold" />

</FrameLayout>

     這樣就可以在地圖上面顯示我們自定義的Marker了 , 那現在問題來了 , 如果我點擊Marker會有什麼效果呢 ? Marker點擊事件需要設置監聽才能響應 , 那就實現點擊Marker放大的效果吧

     非常坑爹的一個就是 , 並沒有找到直接在原有Marker的基礎上修改樣式的方法 , 目前我是在點擊Marker時 將之前的Marker移除掉 , 然後重新添加一個新的Marker , 以此來產生點擊效果 , 

aMap.setOnMarkerClickListener(this);

 @Override
    public boolean onMarkerClick(Marker marker) {
        //step 1 , reset  將上次的marker恢復到初始狀態
        if (markerPre != null && !marker.equals(markerPre) && markerIndexPre != -1) {
            markerPre.remove();
            View view = View.inflate(this, R.layout.item_marker, null);
            ((TextView) view.findViewById(R.id.num)).setText(String.valueOf(markerIndexPre));
            ((ImageView) view.findViewById(R.id.img)).setImageResource(R.drawable.ic_location_blue_small);

            markers.put(markerIndexPre, aMap.addMarker(new MarkerOptions()
                    .icon(BitmapDescriptorFactory.fromView(view))
                    .position(markerPre.getPosition())));
        }
        if (!marker.equals(markerPre)) {
            int clickIndex = -1;
            for (Map.Entry<Integer, Marker> entry : markers.entrySet()) {
                if (marker.equals(entry.getValue())) {
                    clickIndex = entry.getKey();
                    break;
                }
            }
            if (clickIndex != -1) {
                marker.remove();
                View view = View.inflate(this, R.layout.item_marker, null);
                ((TextView) view.findViewById(R.id.num)).setText(String.valueOf(clickIndex));
                ((ImageView) view.findViewById(R.id.img)).setImageResource(R.drawable.ic_location_blue_big);
                Marker addMarker = aMap.addMarker(new MarkerOptions()
                        .icon(BitmapDescriptorFactory.fromView(view))
                        .position(marker.getPosition()));
                markers.put(clickIndex, addMarker);
                startAnimation(addMarker);
                recyclerView.smoothScrollToPosition(clickIndex - 1);
                locationAdapter.refreshIndex(clickIndex - 1);
                markerPre = addMarker;
                markerIndexPre = clickIndex;
            }
        }       
        return false;
    }
Caption

   

那地圖上能不能繪製 圈兒圈兒 涅? 嘻嘻...api已經提供了方法 顧名思義 , 看到方法名就知道啥意思了

Circle circleOut = aMap.addCircle(new CircleOptions().center(latLng)//圈兒圈兒的座標
                .radius(maxRadius)//圈兒圈兒的半徑R
                .strokeColor(ContextCompat.getColor(this, android.R.color.transparent))
                .fillColor(ContextCompat.getColor(this, R.color.blue_sharder))
                .strokeWidth(0));

   就畫個圈兒圈兒會不會太單調了呀 , 要不乾脆把系統的小藍點幹掉吧 , 自己寫個圈兒圈兒補上 , 思路:外圈兒 套 內圈兒 , 內圈兒套 中心點 , 外圈兒半徑R和中心點固定 , 內圈做動畫通過不斷的改變半徑來實現雷達掃描的效果

private void refreshMyLocation(LatLng latLng) {
        aMap.clear();
        clearCircle();
        // 繪製不同半徑的圓,添加到地圖上
        final Circle circleOut = aMap.addCircle(new CircleOptions().center(latLng)
                .radius(maxRadius)
                .strokeColor(ContextCompat.getColor(this, android.R.color.transparent))
                .fillColor(ContextCompat.getColor(this, R.color.blue_sharder))
                .strokeWidth(0));

        final Circle circleIn = aMap.addCircle(new CircleOptions().center(latLng)
                .radius(10)
                .strokeColor(ContextCompat.getColor(this, android.R.color.transparent))
                .fillColor(ContextCompat.getColor(this, R.color.green_sharder))
                .strokeWidth(0));

        aMap.addMarker(new MarkerOptions()
                .anchor(0.5f, 0.5f)
                .setFlat(true)//平貼地面
                .icon(BitmapDescriptorFactory.fromView(View.inflate(this, R.layout.item_location_point, null)))
                .position(latLng));

        listCircle.add(circleOut);
        listCircle.add(circleIn);
        startAnimator(circleIn);
    }

    private void clearCircle() {
        if (valueAnimator != null && valueAnimator.isRunning()) {
            valueAnimator.cancel();
        }
        for (int i = 0; i < listCircle.size(); i++) {
            listCircle.get(i).remove();
            listCircle.remove(i);
        }
    }

    private void startAnimator(final Circle circle) {
        valueAnimator = ValueAnimator.ofFloat(10, maxRadius).setDuration(3000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAnimatorValue = (float) animation.getAnimatedValue();
                circle.setRadius(mAnimatorValue);//在這裏改變半徑 不斷繪製
            }
        });
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setRepeatMode(ValueAnimator.REVERSE);//反向重複執行,可以避免抖動
        valueAnimator.start();
    }

  哈哈 , 還不錯!  博客圖片大小限制,壓縮的有點模糊,湊活看吧

Caption

    接下就是Poi 搜索了 , 話說Poi是個啥? Point of Interest興趣點 , 就是個關鍵詞搜索 , 這個是sdk自帶的接口 , 返回與我們的關鍵詞相關的一些數據  

//查詢條件
PoiSearch.Query(String keyWord,String p2,String cityCode) ; 

keyWord表示搜索字符串

第二個參數表示POI搜索類型,二者選填其一,選用POI搜索類型時建議填寫類型代碼,碼錶可以參考下方(而非文字)

cityCode表示POI搜索區域,可以是城市編碼也可以是城市名稱,也可以傳空字符串,空字符串代表全國在全國範圍內進行搜索

//創建查詢條件
PoiSearch.Query query = new PoiSearch.Query(keyWord, "", "");
if (poiSearch == null) {
                        poiSearch = new PoiSearch(MapActivity.this, query);
                        poiSearch.setOnPoiSearchListener(new                 PoiSearch.OnPoiSearchListener() {
                            @Override
                            public void onPoiSearched(PoiResult poiResult, int i) {
                                //搜索結果在這裏解析
                                PoiItem poiItem = poiResult.getPois().get(j);
                                LatLonPoint latLonPoint = poiItem.getLatLonPoint();
                                latLng = new LatLng(latLonPoint.getLatitude(),             
                                latLonPoint.getLongitude());
                                locationInfo = new LocationInfo();
                                locationInfo.setLatitude(latLonPoint.getLatitude());
                                locationInfo.setLongitude(latLonPoint.getLongitude());
                                locationInfo.setAddressName(poiItem.getTitle());
                                locationInfo.setAddress(poiItem.getAdName());
                            }

                            @Override
                            public void onPoiItemSearched(PoiItem poiItem, int i) {

                            }
                        });
                    } else {
                        poiSearch.setQuery(query);
                    }
//開始異步搜索
 poiSearch.searchPOIAsyn();

  可以從PoiItem  中獲取座標信息,  poiItem.getTitle() 是Poi的名稱 ,關於PoiItem的詳細api可以參開開放平臺的api的文檔http://a.amap.com/lbs/static/unzip/Android_Map_Doc/index.html

  來展示下最終的效果

 

Caption

  代碼已在GitHub託管,https://github.com/good-good-study/WeChartApplication

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章