Android編程 高德地圖 中如何重寫 定位按鍵 的觸發事件 (com.amap.api.maps2d.LocationSource)點擊定位後不只定位在地圖中心點上並且能夠設置地圖的縮放大小和提示

在利用高德地圖來編寫本身的APP的時候,發現了一種對定位按鍵的重寫方法,那就是利用   com.amap.api.maps2d.LocationSource  接口來重寫。html

 

什麼是定位按鍵呢,下圖中右上角那個就是。java

 

 

 

 

import com.amap.api.maps2d.AMap;
private AMap aMap;//地圖控制器對象
//aMap 爲地圖控制器對象
aMap.getUiSettings().setMyLocationButtonEnabled(true);//地圖的定位標誌是否可見
aMap.setMyLocationEnabled(true);//地圖定位標誌是否能夠點擊




上面的語句是設置 顯示定位按鍵,而且使其能夠被點擊的語句。






要想使activity 中 重寫 定位按鍵的 激發事件 就須要實現接口 LocationSource , 以下:
import com.amap.api.maps2d.LocationSource;

public class GetMyLocationActivity extends AppCompatActivity implements LocationSource





首先, aMap.setLocationSource(this);//設置了定位的監聽,這裏要實現LocationSource接口
這一步的操做就是說定位按鍵的監聽對象爲 this對象。

而後,須要定義一個 LocationSource 接口中的一個嵌套接口, OnLocationChangedListener
OnLocationChangedListener mListener;

而後, 實現 LocationSource 接口中的兩個方法:
    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        mListener = onLocationChangedListener;
        //aMap.moveCamera(CameraUpdateFactory.zoomTo(18));
     //Toast.makeText(getApplicationContext(), "定位按鍵啓動", Toast.LENGTH_SHORT).show();
} @Override public void deactivate() { mListener = null; }
 

上面的兩個實現的接口中的方法是一對, activate 是定位按鍵點擊時的觸發事件, 將傳入的對象  onLocationChangedListener 賦給類屬性 mListener ,   該語句的意思是 使類屬性 mListener 指向定位按鍵的監聽器對象, 也就是說兩個對象是同一塊內存的對象。android

deactivate  是指定位按鍵結束事件, 將  mListener   對象所指向的對象設置爲空,即沒有內存空間的一個對象, 該步驟至關因而一個防止出現垃圾內存的一個回收方式。git

 

將代碼改寫爲以下,加入調試信息:api

@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mListener = onLocationChangedListener;
Log.v("mlistener", ""+mListener);
//aMap.moveCamera(CameraUpdateFactory.zoomTo(18));
}

 

以上的調試信息是如何操做的呢?緩存

進入activity, 打印了一次,點擊定位後又顯示了一次,這兩次的結果相同,能夠看到在一個activity 的生命週期中 監聽器的對象不變。app

當activity 消亡後再次進入, 發現對象的空間改變,能夠看出在不一樣activity 生命週期中 監聽器對象   是不一樣的。ide

 

 其中一個比較神奇的發現就是, 在進入activity的同時,activate 方法會被執行,此時並無手動點擊定位按鍵。函數

 

 

下面一個步驟是我一直沒有太想明白的一個操做,下面也只是寫一下本身的一些理解:this

定位按鍵的  激發事件 和  銷燬事件已經寫完了, 下一步則是要將 定位按鍵的監聽器對象 註冊給定位後的操做。

也就是說 點擊定位按鍵後, mListener 是被設置爲監聽位置更新的一個對象,mListener所對應的空間爲傳進來的一個對象。

那麼剩下來的操做就是將 mListener 監聽器註冊給位置更新後觸發的事件, mListener 是監聽位置更新的監聽器,mListener 所監聽的位置對象爲 amapLocation,  該對象是定位事件中所得到的定位對象。

 

mListener.onLocationChanged(amapLocation);

 

關鍵代碼以下:

 
    public AMapLocationListener mLocationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation amapLocation) {
            if (amapLocation != null) {
                if (amapLocation.getErrorCode() == 0) {
                    Log.v("getLocationType", ""+amapLocation.getLocationType() ) ;
                    lat = amapLocation.getLatitude();
                    lon = amapLocation.getLongitude();

                    Log.v("getAccuracy", ""+amapLocation.getAccuracy()+" 米");//獲取精度信息
                    Log.v("joe", "lat :-- " + lat + " lon :--" + lon);
                    Log.v("joe", "Country : " + amapLocation.getCountry() + " province : " + amapLocation.getProvince() + " City : " + amapLocation.getCity() + " District : " + amapLocation.getDistrict());
                    //清空緩存位置
                    aMap.clear();

                    if( isFirstLoc ) {
                        // 設置顯示的焦點,即當前地圖顯示爲當前位置
                        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lon), 18));
                        //aMap.moveCamera(CameraUpdateFactory.zoomTo(18));
                        //aMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(lat, lon)));

                        //點擊定位按鈕 可以將地圖的中心移動到定位點
 mListener.onLocationChanged(amapLocation);
                        isFirstLoc=false;
                    }
 

 

最終,我的的理解是 mListener 是定位按鍵的一個監聽器, 也就是說按下了一次定位按鍵,那麼 mListener 監聽器就會被調用,
mListener 定位到如今的位置信息是使用 mListener.onLocationChanged(amapLocation) 語句來進行設置的。


mListener 在第一次進入activity 的時候被賦值, 點擊按鍵也會被在次賦值此時意義不大,能夠將代碼:


boolean isFirstLoc2=true;
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mListener = onLocationChangedListener;

Toast.makeText(getApplicationContext(), "定位到個人位置", Toast.LENGTH_SHORT).show();
//aMap.moveCamera(CameraUpdateFactory.zoomTo(18));
}
修改成:
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
if( isFirstLoc2 ) {
mListener = onLocationChangedListener;
isFirstLoc2=false;}
Toast.makeText(getApplicationContext(), "定位到個人位置", Toast.LENGTH_SHORT).show();
//aMap.moveCamera(CameraUpdateFactory.zoomTo(18));
}



===============================================================

其中,有一個問題,很久纔想明白,
 mListener.onLocationChanged(amapLocation);
amapLocation 是位置信息, 隨着時間推移 位置信息是不斷變化的, 這是否可行?
後來 發現 amapLocation 對象 是屬於 AMapLocation類的。

類 AMapLocation

 
  • java.lang.Object
    • Location
      • com.amap.api.location.AMapLocation
 
全部已實現的接口:
java.lang.Cloneable



也就是說, amapLocation 雖然會不斷的被傳入新值, 可是其所對應的內存空間是不變的, 也就是說對象是不變的,變的是其屬性值。







完整代碼以下:
package com.joe.ditudemo.fuction;

import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps2d.AMap;
import com.amap.api.maps2d.AMapOptions;
import com.amap.api.maps2d.CameraUpdateFactory;
import com.amap.api.maps2d.LocationSource;
import com.amap.api.maps2d.MapView;
import com.amap.api.maps2d.UiSettings;
import com.amap.api.maps2d.model.BitmapDescriptor;
import com.amap.api.maps2d.model.BitmapDescriptorFactory;
import com.amap.api.maps2d.model.LatLng;
import com.amap.api.maps2d.model.Marker;
import com.amap.api.maps2d.model.MarkerOptions;
import com.joe.ditudemo.R;

import static com.amap.api.location.AMapLocationClientOption.AMapLocationMode.Hight_Accuracy;

/**
 * Created by Joe.
 */

public class GetMyLocationActivity extends AppCompatActivity implements LocationSource {

    //聲明AMapLocationClient類對象
    public AMapLocationClient mLocationClient = null;
    //聲明mLocationOption對象
    public AMapLocationClientOption mLocationOption = null;
    private double lat;
    private double lon;
    private MapView mapView;
    private AMap aMap;//地圖控制器對象
    private UiSettings mUiSettings;

    OnLocationChangedListener mListener;

    boolean isFirstLoc = true;
    boolean isFirstLoc2 = true;

    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        if( isFirstLoc2 ) {
            mListener = onLocationChangedListener;
            isFirstLoc2=false;}
        //Toast.makeText(getApplicationContext(), "定位到個人位置", Toast.LENGTH_SHORT).show();
        aMap.moveCamera(CameraUpdateFactory.zoomTo(18));
    }

    @Override
    public void deactivate() {
        mListener = null;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_get_mylocation);
        //初始化定位
        mLocationClient = new AMapLocationClient(getApplicationContext());
        //設置定位回調監聽
        mLocationClient.setLocationListener(mLocationListener);//設置其爲定位完成後的回調函數
        mapView = (MapView) findViewById(R.id.mapView);
        mapView.onCreate(savedInstanceState);
        init();

    }

    /**
     * * 初始化AMap類對象 aMap 地圖控制器
     */
    private void init() {
        if (aMap == null) {
            aMap = mapView.getMap();//地圖控制器對象
            aMap.setLocationSource(this);//設置了定位的監聽,這裏要實現LocationSource接口
            mUiSettings = aMap.getUiSettings();
        }
        //設置logo位置
        mUiSettings.setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_CENTER);//高德地圖標誌的擺放位置
        mUiSettings.setZoomControlsEnabled(true);//地圖縮放控件是否可見
        mUiSettings.setZoomPosition(AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM);//地圖縮放控件的擺放位置
        //aMap  爲地圖控制器對象
        aMap.getUiSettings().setMyLocationButtonEnabled(true);//地圖的定位標誌是否可見
        aMap.setMyLocationEnabled(true);//地圖定位標誌是否能夠點擊

        setUpMap();
    }


    /**
     * 配置定位參數
     */
    private void setUpMap() {

        //初始化定位參數
        mLocationOption = new AMapLocationClientOption();

        //設置定位模式爲高精度模式,Battery_Saving爲低功耗模式,Device_Sensors是僅設備模式
        mLocationOption.setLocationMode(Hight_Accuracy);

        //設置是否返回地址信息(默認返回地址信息)
        mLocationOption.setNeedAddress(true);

        //設置是否只定位一次,默認爲false
        mLocationOption.setOnceLocation(false);

        //設置是否容許模擬位置,默認爲false,不容許模擬位置
        mLocationOption.setMockEnable(false);

        //設置定位間隔,單位毫秒,默認爲2000ms
        mLocationOption.setInterval(2000);

        //給定位客戶端對象設置定位參數
        mLocationClient.setLocationOption(mLocationOption);

        //啓動定位
        mLocationClient.startLocation();
    }

    public AMapLocationListener mLocationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation amapLocation) {
            if (amapLocation != null) {
                if (amapLocation.getErrorCode() == 0) {
                    Log.v("getLocationType", ""+amapLocation.getLocationType() ) ;
                    lat = amapLocation.getLatitude();
                    lon = amapLocation.getLongitude();

                    Log.v("getAccuracy", ""+amapLocation.getAccuracy()+" 米");//獲取精度信息
                    Log.v("joe", "lat :-- " + lat + " lon :--" + lon);
                    Log.v("joe", "Country : " + amapLocation.getCountry() + " province : " + amapLocation.getProvince() + " City : " + amapLocation.getCity() + " District : " + amapLocation.getDistrict());
                    //清空緩存位置
                    aMap.clear();

                    if( isFirstLoc ) {
                        // 設置顯示的焦點,即當前地圖顯示爲當前位置
                        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lon), 18));
                        //aMap.moveCamera(CameraUpdateFactory.zoomTo(18));
                        //aMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(lat, lon)));

                        //點擊定位按鈕 可以將地圖的中心移動到定位點
                        mListener.onLocationChanged(amapLocation);
                        isFirstLoc=false;
                    }

                    MarkerOptions markerOptions = new MarkerOptions();
                    markerOptions.position(new LatLng(lat, lon));
                    markerOptions.title("個人位置");
                    markerOptions.visible(true);
                    BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.icon_location));
                    markerOptions.icon(bitmapDescriptor);
                    markerOptions.draggable(true);
                    Marker marker = aMap.addMarker(markerOptions);
                    marker.showInfoWindow();
                } else {
                    //顯示錯誤信息ErrCode是錯誤碼,errInfo是錯誤信息,詳見錯誤碼錶。
                    Log.e("joe", "location Error, ErrCode:"
                            + amapLocation.getErrorCode() + ", errInfo:"
                            + amapLocation.getErrorInfo());
                }
            }
        }
    };

    /**
     * 從新繪製加載地圖
     */
    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

    /**
     * 暫停地圖的繪製
     */
    @Override
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }

    /**
     * 保存地圖當前的狀態方法必須重寫
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }

    /**
     * 銷燬地圖
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
        if (mLocationClient != null) {
            mLocationClient.stopLocation();
            mLocationClient.onDestroy();
        }
        mLocationClient = null;
    }
}
 

 

 

 

參考文章:

https://blog.csdn.net/PenTablet/article/details/78273743

http://www.apkbus.com/blog-904057-63610.html

相關文章
相關標籤/搜索