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

												

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

  1. Android 编程 高德地图 (实现显示地图以及定位功能)

    本文参考文章: http://www.apkbus.com/blog-904057-63610.html 本人实现的 定位代码:(具体配置省略,可见参考文章) package com.example. ...

  2. Android常用的物理按键及其触发事件

    Activity和View都能接收触摸和按键,如果响应事件只需要在继承类里复写事件函数即可:当一个视图(如一个按钮)被触摸时,该对象上的 onTouchEvent() 方法会被调用.不过,为了侦听这个 ...

  3. Android 编程 AMapLocationClientOption 类中的 setNeedAddress 方法用处 (高德地图 com.amap.api.location.AMapLocationClientOption 中的类)

    最近在用高德地图来写Android App, 其中有一些 方法是不太理解的,这里写一下 对  高德地图  com.amap.api.location.AMapLocationClientOption ...

  4. Android 编程 AMapLocationClientOption 类中的 setMockEnable (高德地图 com.amap.api.location.AMapLocationClientOption 中的类)

    setMockEnable 高德地图中 AMapLocationClientOption 中有一个方法是设置APP是否接受模拟定位的设置,就是方法 setMockEnable //设置是否允许模拟位置 ...

  5. Android编程 高德地图 AMapLocationClientOption 类中 setWifiActiveScan过时

    高德地图中   定位包中有以下方法: AMapLocationClientOption  类中  setWifiActiveScan  过时 isWifiActiveScan public boole ...

  6. 【转载】Delphi7从子线程中发送消息到主线程触发事件执行

    在对数据库的操作时,有时要用一个子线程来进行后台的数据操作.比如说数据备份,转档什么的.在主窗口还能同是进行其它操作.而有时后台每处理一个数据文件,要向主窗口发送消息,让主窗口实时显示处理进度在窗口上 ...

  7. LayUI中select下拉框选中触发事件

    代码: var form = layui.form, layer = layui.layer; // 监听 $(document).ready(function() { // select下拉框选中触 ...

  8. android编程——百度地图初探

    项目需要,花了一天时间研究了下百度地图的API,其实看起来可能会有点困难,但是将它的DEMO跑起来之后一切都迎刃而解的样子了.百度方面讲地图的接口封装的挺不错的,而且现在能够提供的地图的服务也有将近十 ...

  9. [电子书] 《Android编程兵书》PDF

    Android编程兵书 内容简介: 这是一本Android开发书籍,内容讲解详细,例子丰富,能帮助读者举一反三.在<Android编程兵书>中,每一个知识点的描述都非常详细,并且每一个知识 ...

随机推荐

  1. CommonLang3 --StringUtils使用指南

    转载自(http://blog.csdn.net/xuxiaoxie/article/details/52095930)public static boolean isEmpty(CharSequen ...

  2. mysql完全卸载

    转载自(http://blog.csdn.net/typa01_kk/article/details/49057073) #################CentOS7下MySQL的卸载###### ...

  3. tomcat配置根目录访问后,部署后第一次访问会出现tomcat的默认界面而非项目首页

    tomcat配置根目录访问后,部署后第一次访问会出现tomcat的默认界面而非项目首页,而重启后会正常,这个原因是因为在配置文件中有如下配置,造成项目加载两次 <Host name=" ...

  4. HA-web-services

    一.HA部署 本次实验的程序选型为heartbeat v1 + hearesources.资源有IP和httpd,filesystem 配置HA集群的前提: (1)各节点资源一致,硬件或软件环境一致 ...

  5. Dockerfile 设置语言包

    最近使用Hangfire的Dashboard, 在本地调试时,显示的是中文,但是通过docker在kubernetes上运行时,就显示成英文了, 怀疑是docker运行环境中没有设计默认的语言包: 我 ...

  6. Interleaving String,交叉字符串,动态规划

    问题描述: Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Give ...

  7. poj 2255 Tree Recovery 分治

    Tree Recovery Description Little Valentine liked playing with binary trees very much. Her favorite g ...

  8. web.config文件配置解决网站上传大文件限制

    Asp.Net网站对上传文件的大小,请求执行的时间都做了限制,上传的文件如果超过限制或者执行上传时间超出, 文件上传都将失败. 因此,需要配置web.config来增加最大文件上传的大小和执行超时时间 ...

  9. Django框架数据库模型

    博主最近开始优化之前的API接口自动化框架,这次打算使用django框架来完成 # -*- coding: utf-8 -*- from __future__ import unicode_liter ...

  10. LR--实现HTTP协议的接口测试

    场景分析:使用LR完成HTTP协议的接口测试 流程: 1.首先需要找一个接口(POST.GET接口) 2.LR中点击Insert-->New Step-->web_custom_reque ...