Android高德SDK 地圖篇三:Marker實現選擇起點

在不少應用中都Marker在地圖控件中間位置不變化:以下圖java

ps:有人說是屏幕這個其實形容不許確 實際上是MapView的中心點,只不過地圖通常都是鋪滿屏幕的,因此纔會有屏幕的說法android

請注意:(在這篇文章中 屏幕指MapView)git

在上一期中 咱們知道 Marker類有   設置Marker像素位置的方法以下markdown

那麼咱們如何取的地圖控件中心點的像素座標呢。網絡

這裏咱們須要瞭解兩個新的類框架

  • CameraPosition

   相機位置,這個類包含了全部的可視區域的位置參數。dom

  這個類是咱們在地圖移動視角後,存儲一些參數以下:ide

在這個類中 target屬性是地圖控件中心點的座標,這個是屬性是咱們等會要使用oop

  • Projection 

這個類負責將屏幕位置和地理座標(經緯度)進行轉換。屏幕位置是相對地圖的左上角的位置,因此並不必定是從整個屏幕開始計算的。學習

這個類重要的是他的方法。請看以下圖

看完上面咱們就應該知道 若是取地圖控件中心點的像素位置了。

咱們要經過CarmeraPositon的target屬性要拿到地圖中心點的座標

經過Projection的toScreenLocation方法來獲取地圖控件中心點的像素位置

代碼以下:

//拿到地圖中心點的座標。
LatLng latLng = aMap.getCameraPosition().target;
//把中心點的座標轉換成屏幕像素位置
Point screenPosition = aMap.getProjection().toScreenLocation(latLng);
//給marker設置像素位置。
marker.setPositionByPixels(screenPosition.x, screenPosition.y);
複製代碼

調用這段代碼須要注意的問題:

若是咱們直接在Activty中的onCreate或者Frgment的onViewCreate方法調用,因爲MapView這個時候的長度和寬度都仍是0,這個時候算出的screenPosition.x screenPosition.y

都爲0.計算的結果是不正確的,你會看不到Marker的,

因此咱們要在MapView的長度和寬度已經算出來的狀況下在調用這個方法,

高德SDK也提供了這個方法代碼以下:

getAMap().setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
    @Override
    public void onMapLoaded() {
       //在這裏調用這個方法,才能顯示出來
        addCenterMarker();
    }
});
複製代碼

移動地圖後獲取中間Marker的座標點(實現選擇起點)

好了 咱們來實現下面的這個效果

首先咱們分析下這個功能,

1. 移動地圖的時候 infoWindow隱藏,

2. 中止移動的時候 infoWindow顯示loading效果。

3. 根據座標的獲取地理名稱後 infoWindow顯示成功。 固然也有失敗的狀況。

根據座標點的獲取地理名稱 在高德上 叫逆地理編碼, 是一個耗時操做(至關於一個網絡請求)

ps:  你們看到那個三分鐘和附近車輛的座標位置, 其實應該是滴滴網絡請求接口返回的,可是我並無這個接口 就直接寫了 3分鐘,附近車輛座標是根據座標點隨機生成。

固然在實際狀況下這樣確定不行 正常狀況應該是:

當咱們中止移動地圖的時候,應該有兩個耗時操做,一個是獲取座標點地理名稱(逆地理編碼),一個是獲取預估時間附近車輛位置(http請求接口),且這兩個耗時操做都要成功 InfoWindow 才能顯示成功。 

這個時候我就很是推薦使用RXJAVA來實現這個功能了。

可是是在這裏咱們主要是介紹高德SDK 儘可能不引入其餘框架,來增長你們的學習成本。

在代碼中我會作一個測試數據來模擬獲取預估時間附近車輛位置(http請求接口) 不使用rxjava

首先咱們瞭解下 一個方法

OnCameraChangeListener:

這個方法會在地圖移動的時候回調。

onCameraChange 會在移動地圖的時候不斷調用

onCameraChangeFinish 會在地圖中止移動的時候的調用
複製代碼

咱們應該

在onCameraChange 隱藏infoWindow

在onCameraChangeFinish 進行逆地理編碼和獲取接駕時間的耗時操做,infoWindow同時顯示loading效果,成功後infoWindow顯示成功 失敗後InfoWindow顯示失敗

咱們把代碼都寫在Fragment中很差 因此咱們封裝一下 

建一個CenterMarkerView類
複製代碼

代碼以下:

/**
 * @author jikun
 *         Created by jikun on 2018/3/14.
 */

public class CenterMarkerView {

    private Marker centerMarker;

    public void addCenterMarker(AMap aMap) {
        MarkerOptions options = new MarkerOptions();
        //對應Marker.setIcon方法  設置Marker的圖片
        options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.icon_me_location));
        options.anchor(0.5F, 1);
        //拿到地圖中心點的座標。
        LatLng latLng = aMap.getCameraPosition().target;
        //把中心點的座標轉換成屏幕像素位置
        Point screenPosition = aMap.getProjection().toScreenLocation(latLng);
        //在地圖上添加Marker並獲取到Marker.
        centerMarker = aMap.addMarker(options);
        //給marker設置像素位置。
        centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y);
        centerMarker.setAnchor(0.5F, 1);

    }

    public void initInfoWindowsView(final Context context, AMap aMap) {
        aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
            @Override
            public View getInfoWindow(Marker marker) {
                View infoWindow = LayoutInflater.from(context).inflate(
                        R.layout.map_fast_car_info_window, null);

                infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.VISIBLE);
                infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.GONE);
                infoWindow.findViewById(R.id.ll_left).setVisibility(View.VISIBLE);
                infoWindow.findViewById(R.id.iv_loading).setVisibility(View.GONE);
                return infoWindow;
            }

            @Override
            public View getInfoContents(Marker marker) {
                return null;
            }
        });
    }


    public void hideCenterMarkerInfoWindow() {

    }

    public void showLoadingInfoWindow() {

    }

    public void showSuccessInfoWindow() {

    }

    public void showErrorInfoWindow() {

    }

    public void destorty() {
        if (null != centerMarker) {
            centerMarker.destroy();
        }


    }
}
複製代碼

當咱們調用Marker.showInfoWindow 方法的時候 InfoWindowAdapter的getInfoWindow()和getInfoContents()會回調

根據這個 咱們先寫一個枚舉類 來區分當前InfoWindow是 加載中 仍是成功 或者失敗的UI效果

註解代碼以下:

//添加支持註解的依賴到你的項目中,須要在build.gradle文件中的依賴塊中添加:
//dependencies { compile 'com.android.support:support-annotations:24.2.0' }
@IntDef({InfoWindowUIType.LOADING, InfoWindowUIType.SUCCESS, InfoWindowUIType.FAILED})
@Retention(RetentionPolicy.SOURCE)
public @interface InfoWindowUIType {

    public static final int LOADING = 0;
    public static final int SUCCESS = 1;
    public static final int FAILED = 2;


}
複製代碼

好了咱們來寫UI控制效果 代碼以下:

public void initInfoWindowsView(final Context context, AMap aMap) {
    aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
        @Override
        public View getInfoWindow(Marker marker) {
            View infoWindow = LayoutInflater.from(context).inflate(
                    R.layout.map_fast_car_info_window, null);
            switch (type) {
                case InfoWindowUIType.LOADING:
                    //Loading InfoWindow顯示效果
                    infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.VISIBLE);
                    infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.GONE);
                    infoWindow.findViewById(R.id.ll_left).setVisibility(View.GONE);
                    infoWindow.findViewById(R.id.iv_loading).setVisibility(View.VISIBLE);

                    ImageView imageView = infoWindow.findViewById(R.id.iv_loading);
                    AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
                    if (!animationDrawable.isRunning()) {
                        animationDrawable.start();
                    }

                    break;
                case InfoWindowUIType.SUCCESS:
                    infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.VISIBLE);
                    infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.GONE);
                    infoWindow.findViewById(R.id.ll_left).setVisibility(View.VISIBLE);
                    infoWindow.findViewById(R.id.iv_loading).setVisibility(View.GONE);
                    break;
                case InfoWindowUIType.FAILED:
                    infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.GONE);
                    infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.VISIBLE);
                    break;
                default:
                    break;
            }

            return infoWindow;
        }

        @Override
        public View getInfoContents(Marker marker) {
            return null;
        }
    });
}
複製代碼

咱們添加一個模擬請求的延遲類

代碼以下

/**
 * @author jikun
 *         Created by jikun on 2018/3/14.
 */

public class DelayTest {
    public OnCallBack callBack;

    public Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (null != callBack) {
                callBack.onSuccess();
            }
        }
    };

    public void getDelayPost(OnCallBack callBack) {
        this.callBack = callBack;
        long sec = (long) (Math.random() * 1300);
        Log.e("測試代碼", "測試代碼時間=" + sec);
        handler.sendEmptyMessageDelayed(0, sec);
    }

    public void stop() {
        this.callBack = null;
    }

    public interface OnCallBack {
        void onSuccess();

        void onFailed();
    }

    public void destory() {
        handler.removeCallbacksAndMessages(null);
    }
}
複製代碼

而後在CenterMarkerMapFragment 的代碼以下:

/**
 * @author jikun
 *         Created by jikun on 2018/3/13.
 */

public class CenterMarkerMapFragment extends BaseMapFragment {

    private CenterMarkerView centerMarkerView;
    private DelayTest delayTest;

    public static CenterMarkerMapFragment newInstance() {

        Bundle args = new Bundle();

        CenterMarkerMapFragment fragment = new CenterMarkerMapFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_marker_map, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        TextureMapView textureMapView = view.findViewById(R.id.textureMapView);
        delayTest = new DelayTest();
        initMapView(textureMapView, savedInstanceState);

        centerMarkerView = new CenterMarkerView();
        centerMarkerView.initInfoWindowsView(getContext(), getAMap());

        getAMap().setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
            @Override
            public void onMapLoaded() {
                centerMarkerView.addCenterMarker(getAMap());
                moveCameraOnMap();
            }
        });
        getAMap().setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
            @Override
            public void onCameraChange(CameraPosition cameraPosition) {
                delayTest.stop();
                centerMarkerView.hideCenterMarkerInfoWindow();


            }

            @Override
            public void onCameraChangeFinish(CameraPosition cameraPosition) {

                centerMarkerView.showLoadingInfoWindow();

                delayTest.getDelayPost(new DelayTest.OnCallBack() {
                    @Override
                    public void onSuccess() {
                        centerMarkerView.showSuccessInfoWindow();
                    }

                    @Override
                    public void onFailed() {
                        centerMarkerView.showErrorInfoWindow();

                    }
                });


            }
        });


    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        centerMarkerView.destorty();
        delayTest.destory();
    }


    /**
     * 移動地圖到Marker標記點位置的方法。
     */
    private void moveCameraOnMap() {
        LatLng latLng = new LatLng(30.657505, 104.065692);
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(latLng);
        getAMap().moveCamera(cameraUpdate);
    }
複製代碼

最後咱們就實現以下效果

因爲篇幅問題,

逆地理編碼和 顯示周圍車輛我就放在下一篇中講解了。

代碼下載地址:gitee.com/justforgame…

相關文章
相關標籤/搜索