今天接入了高德地图,想着大概半年前做高德地图的时候,完全看不懂代码,在那里看着官方的东西到凌晨两点还是看不懂,最后只能直接去复制别人的代码来用。虽然成功了,但是一直不知道为什么,而且那只是简简单单地实现一个定位并在地图上显示出来而已。

今天在以一个第一次使用的心态去看时,发现这次就看懂了这里了,再加上请教了一下别人,这个功能很快就能理解了。

代码不多:

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);
        }
    }
}