未经允许,禁止转载,违者必究!
浣熊我最近在研究高德地图android api,看到第三章定位信息后半部分关于“如何通过MyLocationOverlay 实现自动定位”的时候我凌乱了,写得过于简单,根本不知道如何操作。最后通过阅读官方的示例代码和在网上搜集大量资料实现了地图自动定位的功能。
开发指南第三章定位信息前半部分的代码实现的功能是:当手机采集的地理位置(经纬度)发生改变时在界面上显示出改变后的经纬度。如果开发过android原生定位程序的开发者应该对这部分代码不陌生,中规中矩,先注册位置监听服务,然后当位置发生改变后出发onLocationChanged()方法。现在请在官网上下载示例代码,导入工程后开启包com.amap.cn.apis.location中的MyLocation.java文件,该文件实现的主要功能是:初始化地图并且实现首次定位,地图会自动移动到定位点,我们一会便要基于这个文件来完成地图自动实时定位的功能。
看到这儿,有人可能想把MyLocation文件中的内容与第三章给出的android原生定位模块简单整合。如果你的解决思路是:在onLocationChanged()方法中企图在地图上绘制出当前的位置,那么就会遇到很大的麻烦。因为如果用高德地图提供的api在地图上绘制定位点的话一定要调用类MyLocationOverlay中的enableMyLocation()方法,根据官方参考资料,这个方法封装了android原生的类LocationManager中的requestLocationUpdates()方法,所以你在写onLocationChanged()方法前一定是已经调用了原生的类LocationManager中的requestLocationUpdates()方法,这样一来造成了LocationManager在没有removeUpdate前又进行了一次requestLocationUpdates,由此造成程序意外退出。
所以还是回到开发指南第三章,好好看看后半部分:如果想让地图跟随当前位置移动,需要继承MyLocationOverlay 并实现其onLocationChanged()方法,调用MapView.getController().animateTo()方法移动地图位置。官方用户指南上的这句原话正是问题的正解,不过官网实在太坑爹,简简单单几行文字和代码,对于浣熊这种刚刚接触地图开发的小白来说实在是看得一头雾水,还在一阵瞎折腾,终于解决了问题,所以共享出来,希望和我一样的小白能够少走些弯路。
我先把修改后的MyLocation.java文件整个贴出来,在增加或改动的代码前后均表明了注释(不包括包的改动):“/*change start*/”和"/*change end*/"
/** * 使用MyLocationOverlay实现地图自动定位 * 实现初次定位使定位结果居中显示 */public class MyLocation extends MapActivity { private MapView mMapView; private MapController mMapController; private GeoPoint point; /*change start*/ private MyLocationOverlay_HX mLocationOverlay; /*change end*/ /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mapview); mMapView = (MapView) findViewById(R.id.mapView); mMapView.setBuiltInZoomControls(true); mMapController = mMapView.getController(); point = new GeoPoint((int) (39.90923 * 1E6), (int) (116.397428 * 1E6)); //用给定的经纬度构造一个GeoPoint,单位是微度 (度 * 1E6) mMapController.setCenter(point); //设置地图中心点 mMapController.setZoom(15); /*change start*/ mLocationOverlay = new MyLocationOverlay_HX(this, mMapView); /*change end*/ mMapView.getOverlays().add(mLocationOverlay); //实现初次定位使定位结果居中显示 mLocationOverlay.runOnFirstFix(new Runnable() { public void run() { handler.sendMessage(Message.obtain(handler, Constants.FIRST_LOCATION)); } }); } /*change start*/ class MyLocationOverlay_HX extends MyLocationOverlay { public MyLocationOverlay_HX(Context arg0, MapView arg1) { super(arg0, arg1); // TODO Auto-generated constructor stub } public void onLocationChanged(Location location) { //Toast.makeText(getApplicationContext(), "Location Changed",Toast.LENGTH_LONG).show(); point = new GeoPoint((int) (location.getLatitude() * 1E6), (int) (location.getLongitude() * 1E6)); //用给定的经纬度构造一个GeoPoint,单位是微度 (度 * 1E6) //mMapController.setCenter(point); //设置地图中心点 mMapController.animateTo(point); super.onLocationChanged(location); } } /*change end*/ @Override protected void onPause() { this.mLocationOverlay.disableMyLocation(); super.onPause(); } @Override protected void onResume() { this.mLocationOverlay.enableMyLocation(); super.onResume(); } private Handler handler = new Handler() { public void handleMessage(Message msg) { if (msg.what == Constants.FIRST_LOCATION) { mMapController.animateTo(mLocationOverlay.getMyLocation()); } } };}最关键就在于我在程序中继承了类MyLocationOverlay,将继承类命名为MyLocationOverlay_HX,并在其中重写了onLocationChanged()方法,从代码中可以看出,当位置改变时会触发 类MyLocationOverlay的onLocationChanged()方法,然后可以获取位置的经纬度坐标信息,由该信息构建point数据结构,并将其传给类MapController的animateTo()方法,即可以动画的形式移动到新的定位点去,实现实时自动地图定位的功能。