今天接入了高德地图,想着大概半年前做高德地图的时候,完全看不懂代码,在那里看着官方的东西到凌晨两点还是看不懂,最后只能直接去复制别人的代码来用。虽然成功了,但是一直不知道为什么,而且那只是简简单单地实现一个定位并在地图上显示出来而已。
今天在以一个第一次使用的心态去看时,发现这次就看懂了这里了,再加上请教了一下别人,这个功能很快就能理解了。
代码不多:
public class MainActivity extends AppCompatActivity {
private MapView mapview;
private AMap aMap;
private AMapLocationClient aMapLocationClient = null;
private AMapLocationListener aMapLocationListener ;
private LocationSource.OnLocationChangedListener mOnLocationChangedListener;
private AMapLocationClientOption aMapLocationClientOption;
private MarkerOptions markerOptions;
private MyMarker myMarker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapview = (MapView) findViewById(R.id.mapview);
mapview.onCreate(savedInstanceState);
if (aMap == null){
aMap = mapview.getMap();
}
aMapLocationClient = new AMapLocationClient(this);
initClientOption();
initLocationListener();
aMapLocationClient.setLocationListener(aMapLocationListener);
aMapLocationClient.setLocationOption(aMapLocationClientOption);
aMapLocationClient.startLocation();
}
private void initLocationListener() {
aMapLocationListener = new AMapLocationListener() {
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if(null != aMapLocation){
if(aMapLocation.getErrorCode() == 0){
Log.i("定位成功" , "定位成功");
aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(aMapLocation.getLatitude() , aMapLocation.getLongitude())));
aMap.moveCamera(CameraUpdateFactory.zoomTo(15));
aMap.clear();
myMarker = new MyMarker.MyMarkerBuilder(MainActivity.this).
addIcon(R.mipmap.ic_launcher).
addPoint(new LatLng(aMapLocation.getLatitude() , aMapLocation.getLongitude())).
build();
aMap.addMarker(myMarker.getMyMarkerOption());
}
else {
Toast.makeText(MainActivity.this , "定位失败" , Toast.LENGTH_SHORT).show();
}
}else {
Toast.makeText(MainActivity.this , "定位失败" , Toast.LENGTH_SHORT).show();
}
}
};
}
/**
* 初始化客户端选项
*/
private void initClientOption() {
aMapLocationClientOption = new AMapLocationClientOption();
//设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式。
aMapLocationClientOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
// //设置定位模式为AMapLocationMode.Battery_Saving,低功耗模式。
// aMapLocationClientOption.setLocationMode(AMapLocationMode.Battery_Saving);
// //设置定位模式为AMapLocationMode.Device_Sensors,仅设备模式。
// aMapLocationClientOption.setLocationMode(AMapLocationMode.Device_Sensors);
//获取一次定位结果:
//该方法默认为false。
//aMapLocationClientOption.setOnceLocation(true);
//获取最近3s内精度最高的一次定位结果:
//设置setOnceLocationLatest(boolean b)接口为true,启动定位时SDK会返回最近3s内精度最高的一次定位结果。
// 如果设置其为true,setOnceLocation(boolean b)接口也会被设置为true,反之不会,默认为false。
//aMapLocationClientOption.setOnceLocationLatest(true);
//设置定位间隔,单位毫秒,默认为2000ms,最低1000ms。 如果设置了上面的一次定位,则这里的连续定位无效,所以一次定位的方法是默认为false
aMapLocationClientOption.setInterval(2000);
//设置是否返回地址信息(默认返回地址信息)
aMapLocationClientOption.setNeedAddress(true);
//设置是否强制刷新WIFI,默认为true,强制刷新。
aMapLocationClientOption.setWifiActiveScan(false);
//设置是否允许模拟位置,默认为false,不允许模拟位置
aMapLocationClientOption.setMockEnable(false);
//单位是毫秒,默认30000毫秒,建议超时时间不要低于8000毫秒。
aMapLocationClientOption.setHttpTimeOut(20000);
//关闭缓存机制
aMapLocationClientOption.setLocationCacheEnable(true);
}
@Override
protected void onDestroy() {
super.onDestroy();
mapview.onDestroy();
}
@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);
}
}
我还是像一开始一样不理解定位和地图显示的问题,后来才知道原来这就是两个不同的东西,地图是地图,定位是定位。要想在地图上显示位置,需要先通过定位来获得位置,再把位置拿给地图用,让地图移动到那个位置。
所以单单看地图的初始化是这些代码:
这里把我们的地图这个控件里面的地图传给aMap。
mapview = (MapView) findViewById(R.id.mapview);
mapview.onCreate(savedInstanceState);
if (aMap == null){
aMap = mapview.getMap();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapview.onDestroy();
}
@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);
}
然后接下来是定位的代码:
aMapLocationClient = new AMapLocationClient(this);
initClientOption();
initLocationListener();
aMapLocationClient.setLocationListener(aMapLocationListener);
aMapLocationClient.setLocationOption(aMapLocationClientOption);
aMapLocationClient.startLocation();
1.先实例化位置客户端
2.初始化客户端的设置,如精确度啊,定位的请求间隔时间啊等。
3.对位置变化的监听器进行设置,就是当位置发生改变的时候,会发生什么操作。
3.1这里我就设置了当位置发生改变的时候,地图移动到我所定位的位置,并设精度为15;
3.2将地图上的东西清理掉(因为接下来我要设置一个标志来将我的位置在地图上显示,不然你只能看到地图显示你所在的区域,而没有显示位置)
3.2设置标志(我用了一张默认图,并把获取到的位置的经纬度传给这个标识,然后再让地图把这个有位置的标识添加到自己身上,这样就显示出了我的位置了)。
附:这里刚好当时看了java的builder模式,就想着尝试一下这种写法,就对这个标识进行开刀了,在使用别人的控件的时候就发现有这种写法,一开始也是不理解,现在觉得蛮好看的。
MyMarker:如果到时还要对标识设置什么就模仿着往上加就行了。就是代码有些多,但写出来我觉得很好看,很清晰,我开始喜欢这种写法了,朋友告诉我好像是链式编程。
/**
* 自定义定位标识
*/
public class MyMarker {
private Context myContext;
private int myIconId;
private LatLng myPoint;
public int getMyIconId() {
return myIconId;
}
public LatLng getMyPoint() {
return myPoint;
}
private MyMarker(MyMarkerBuilder myMarkerBuilder){
this.myIconId = myMarkerBuilder.mIconId;
this.myPoint = myMarkerBuilder.mPoint;
this.myContext = myMarkerBuilder.mContext;
}
/**
* 返回已经设置好的MarkerOptions对象
* @return
*/
public MarkerOptions getMyMarkerOption(){
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(myContext.getResources() , myIconId)));
markerOptions.position(myPoint);
return markerOptions;
}
/**
* 开始设置属性
*/
public static class MyMarkerBuilder{
private Context mContext;
private int mIconId;
private LatLng mPoint;
public MyMarkerBuilder(Context context){
mContext = context;
}
public MyMarkerBuilder addIcon(int iconId){
mIconId = iconId;
return this;
}
public MyMarkerBuilder addPoint(LatLng point){
mPoint = point;
return this;
}
/**
* 构建定位标识的属性
* @return
*/
public MyMarker build(){
return new MyMarker(this);
}
}
}