zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

Android编程 高德地图 中如何重写 定位按键 的触发事件 (com.amap.api.maps2d.LocationSource)点击定位后不仅定位在地图中心点上而且可以设置地图的缩放大小和提示

2023-09-11 14:19:20 时间

在利用高德地图来编写自己的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