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


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

 

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

 

 

 

 

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 指向定位按鍵的監聽器對象, 也就是說兩個對象是同一塊內存的對象。

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

 

將代碼改寫為如下,加入調試信息:

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

 

以上的調試信息是如何操作的呢?

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

當activity 消亡后再次進入, 發現對象的空間改變,可以看出在不同activity 生命周期中 監聽器對象   是不同的。

 

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

 

 

下面一個步驟是我一直沒有太想明白的一個操作,下面也只是寫一下自己的一些理解:

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

也就是說 點擊定位按鍵后, 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




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM