最近项目中需要用到地图的功能,看了下需求后,不多想,直接锁定高德地图,为什么不选择百度地图呢,这里本人觉得高德地图的文档让我看起来更爽,哈哈哈,进入主题吧

前题的申请key这里我就不讲啦,很简单,直接照着官方文档去做就行了。

首先直接上下效果图吧

ANdroid 处理高德坐标漂移 高德坐标定位图_添加marker


首先进来该页面就要实现定位的功能吧,代码如下在这里插入代码片

private AMap aMap;
    private OnLocationChangedListener mListener;
    //声明AMapLocationClient类对象
    private AMapLocationClient mLocationClient;
    private MyLocationStyle myLocationStyle;
    private AMapLocation mapLocation;
    //声明AMapLocationClientOption对象
    public AMapLocationClientOption mapLocationClientOption;
    private String keyWord;
    private PoiSearch.Query query;// Poi查询条件类
    private PoiSearch poiSearch;//搜索
    private PoiSearch.SearchBound searchBound;
    private int currentPage;// 当前页面,从0开始计数
    private PoiResult poiResults; // poi返回的结果
    private String city = "";//搜索城市
    private LatLonPoint latLonPoint;
    private int juli = 10000;
    private Marker marker;
    //地理编码查询类
    GeocodeSearch geocodeSearch;
    MyAdapter adapter;
    List<LocationAddressInfo> data = new ArrayList<>();//自己创建的数据集合
    // 选择的地址
    private String chooseAddress = "";
    LocationAddressInfo fistLineData = new LocationAddressInfo("", "", "", "");

下面是是实现定位所要配置的参数

if (aMap == null) {
        geocodeSearch = new GeocodeSearch(this);
        geocodeSearch.setOnGeocodeSearchListener(this);
        Logger.e(TAG, "aMap");
        aMap = mMapView.getMap();

        myLocationStyle = new MyLocationStyle();
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);
        myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
        aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
        aMap.getUiSettings().setMyLocationButtonEnabled(true);//设置默认定位按钮是否显示,非必需设置。
        aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE);//定位一次
        aMap.moveCamera(CameraUpdateFactory.zoomTo((float) 17.5));

        //设置显示定位按钮 并且可以点击
        UiSettings settings = aMap.getUiSettings();
        aMap.setLocationSource(this);//设置了定位的监听
        aMap.setOnMarkerClickListener(this);
        aMap.setOnMapClickListener(this);
//            aMap.setOnMyLocationChangeListener(location -> {
//                showToast("setOnMyLocationChangeListener");
//            });
            aMap.setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
                @Override
                public void onCameraChange(CameraPosition cameraPosition) {

                    LatLng latLonPoint = marker.getOptions().getPosition();

                }

                @Override
                public void onCameraChangeFinish(CameraPosition cameraPosition) {
                    getAddressByLatlng(cameraPosition.target);
                }
            });
//            aMap.setOnMapLoadedListener(() -> {
//                showToast("setOnMapLoadedListener");
//           });
            settings.setMyLocationButtonEnabled(true);
            aMap.setMyLocationEnabled(true);//显示定位层并且可以触发定位,默认是flase
            mLocationClient = new AMapLocationClient(getApplicationContext());
            mLocationClient.setLocationListener(this);
            //初始化定位参数
            AMapLocationClientOption mLocationOption = new AMapLocationClientOption();
            //设置定位模式为Hight_Accuracy高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            //设置是否返回地址信息(默认返回地址信息)
            mLocationOption.setNeedAddress(true);
            //设置是否只定位一次,默认为false
            mLocationOption.setOnceLocation(false);
            //设置是否强制刷新WIFI,默认为强制刷新
            mLocationOption.setWifiActiveScan(true);
            //设置是否允许模拟位置,默认为false,不允许模拟位置
            mLocationOption.setMockEnable(false);
            //设置定位间隔,单位毫秒,默认为2000ms
            mLocationOption.setInterval(2000);
            //给定位客户端对象设置定位参数
            mLocationClient.setLocationOption(mLocationOption);
            //启动定位
            mLocationClient.startLocation();
        }

-----在定位成功后,会在这个方法中回调
先看下我们所要实现的回调方法

public class LocationActivity extends BaseActivity implements LocationSource, AMapLocationListener, GeocodeSearch.OnGeocodeSearchListener
        , PoiSearch.OnPoiSearchListener, AMap.OnMarkerClickListener, AMap.OnMapClickListener, AMap.InfoWindowAdapter {

这些就是我们要实现的接口,这里不知道为什么要实现这么多接口没关系,下面我们再好好讲解
刚刚我们已经实现定位了,那么定位的回调方法在这个方法里

@Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        if (aMapLocation != null) {
            if (aMapLocation.getErrorCode() == 0) {
                mListener.onLocationChanged(aMapLocation);// 显示系统小蓝点
                StringBuilder stringBuilder = new StringBuilder();
                //定位成功回调信息,设置相关消息
                int type = aMapLocation.getLocationType();
                String address = aMapLocation.getAddress();
                stringBuilder.append(type + address);
                chooseAddress = aMapLocation.getDistrict();
                city = aMapLocation.getCity();
                LatLng latLng = new LatLng(aMapLocation.getLatitude(),
                        aMapLocation.getLongitude());//取出经纬度
                if (marker == null) {
                    marker = aMap.addMarker(new MarkerOptions()
                            .icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.icon_adds)))
                            .snippet("一分钟").position(latLng).draggable(true).setFlat(true));
                    marker.showInfoWindow();
                    aMap.addText(new TextOptions().position(latLng).text(aMapLocation.getAddress()));
                    //固定标签在屏幕中央
                    marker.setPositionByPixels(mMapView.getWidth() / 2, mMapView.getHeight() / 2);
                    marker.setClickable(true);


                } else {
                    //已经添加过了,修改位置即可
                    marker.setPosition(latLng);
                }


                //获得小点
                if (latLonPoint == null) {
                    latLonPoint = new LatLonPoint(aMapLocation.getLatitude(), aMapLocation.getLongitude());
                } else {
                    latLonPoint.setLatitude(aMapLocation.getLatitude());
                    latLonPoint.setLongitude(aMapLocation.getLongitude());
                }
                keyWord = address;
                //根据定位成功后获取地点位置再来搜索
                Logger.e(TAG, JsonParseUtil.toJson(aMapLocation));
                fistLineData.setAddress(aMapLocation.getAddress());
                fistLineData.setStreet(aMapLocation.getStreet());
                //  showToast(aMapLocation.getPoiName());
                doSearchQuery(aMapLocation.getPoiName());
            } else {
                //显示错误信息ErrCode是错误码,errInfo是错误信息,详见下方错误码表。
                Logger.e("erro info:", aMapLocation.getErrorCode() + "---" + aMapLocation.getErrorInfo());
            }
        }

    }

通过回调的方法中的aMapLocation对象,我们可以获得全部的需要的信息了,定位成功之后,我们还要通过获取的定位地点去实现搜索,要不然是没有下面的地址列表的

if (marker == null) {
                    marker = aMap.addMarker(new MarkerOptions()
                            .icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.icon_adds)))
                            .snippet("一分钟").position(latLng).draggable(true).setFlat(true));
                    marker.showInfoWindow();
                    aMap.addText(new TextOptions().position(latLng).text(aMapLocation.getAddress()));
                    //固定标签在屏幕中央
                    marker.setPositionByPixels(mMapView.getWidth() / 2, mMapView.getHeight() / 2);
                    marker.setClickable(true);


                } else {
                    //已经添加过了,修改位置即可
                    marker.setPosition(latLng);
                }

上面这段代码是往地图中添加标志的,可以自行添加需要的图片来标志自己的位置。然后看到这句 doSearchQuery(aMapLocation.getPoiName());这个方法就是根据定位得到的地点名称来搜索该地点的附近信息列表的,接着看下该方法

// showProgressDialog();
        currentPage = 0;
        //第一个参数表示搜索字符串,第二个参数表示poi搜索类型,第三个参数表示poi搜索区域(空字符串代表全国)
        query = new PoiSearch.Query(address, "", city);
        query.setPageSize(30);// 设置每页最多返回多少条poiitem
        query.setPageNum(currentPage);// 设置查第一页
        poiSearch = new PoiSearch(this, query);
        poiSearch.setOnPoiSearchListener(this);//设置回调数据的监听器
        //点附近2000米内的搜索结果
        if (latLonPoint != null) {
            searchBound = new PoiSearch.SearchBound(latLonPoint, juli);
            poiSearch.setBound(searchBound);
        }
        poiSearch.searchPOIAsyn();//开始搜索

不用多说,看注释都知道是搜索的一些配置,然后最后的这句
poiSearch.searchPOIAsyn();//开始搜索就是根据地点发起地理位置搜索的,搜索完后,会在这个方法

@Override
    public void onPoiSearched(PoiResult poiResult, int i) {
        //rCode 为1000 时成功,其他为失败
        Logger.e(TAG, "" + i);
        if (i == AMapException.CODE_AMAP_SUCCESS) {
            // 解析result   获取搜索poi的结果
            if (poiResult != null && poiResult.getQuery() != null) {
                if (poiResult.getQuery().equals(query)) {  // 是否是同一条
                    poiResult = poiResult;
                    // 取得第一页的poiitem数据,页数从数字0开始
                    //poiResult.getPois()可以获取到PoiItem列表
                    List<PoiItem> poiItems = poiResult.getPois();
                    //若当前城市查询不到所需POI信息,可以通过result.getSearchSuggestionCitys()获取当前Poi搜索的建议城市
                    List<SuggestionCity> suggestionCities = poiResult.getSearchSuggestionCitys();
                    //如果搜索关键字明显为误输入,则可通过result.getSearchSuggestionKeywords()方法得到搜索关键词建议。
                    List<String> suggestionKeywords = poiResult.getSearchSuggestionKeywords();
                    data.clear();
                    data.add(fistLineData);
                    //解析获取到的PoiItem列表
                    for (PoiItem item : poiItems) {
                        //获取经纬度对象
                        LatLonPoint llp = item.getLatLonPoint();
                        double lon = llp.getLongitude();
                        double lat = llp.getLatitude();
                        //返回POI的名称
                        String title = item.getTitle();
                        //返回POI的地址
                        String text = item.getSnippet();
                        data.add(new LocationAddressInfo(String.valueOf(lon), String.valueOf(lat), title, text));
                    }
                    data.get(0).setChoose(true);
                    adapter.notifyDataSetChanged();
                }
            } else {
                Toast.makeText(LocationActivity.this, "无搜索结果", Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(LocationActivity.this, "错误码" + i, Toast.LENGTH_SHORT).show();
        }

    }

这个也很简单,首先把获得的地址列表取出 List poiItems = poiResult.getPois();
然后自己创建一个地址类来接受需要的信息,因为我只需要经纬度,市区 和街道的信息,因此我的地址实体类是这样的

public class LocationAddressInfo extends BaseBean {
    private String longitude;  // 纬度
    private String Latitude;  //经度
    private String address;  //地址描述
    private String street;    //街道
    private boolean isChoose;
    public LocationAddressInfo(String longitude,String Latitude,String address,String street){
            this.address=address;
            this.street=street;
            this.longitude=longitude;
            this.Latitude=Latitude;
    }
    public boolean isChoose() {
        return isChoose;
    }

    public void setChoose(boolean choose) {
        isChoose = choose;
    }
    public String getLongitude() {
        return longitude;
    }

    public void setLongitude(String longitude) {
        this.longitude = longitude;
    }

    public String getLatitude() {
        return Latitude;
    }

    public void setLatitude(String latitude) {
        Latitude = latitude;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }
}

下面那部分是把数据填充到recyclerview中并刷新的,没什么好讲的
接下来就是如何实现,移动地图的获取实时的位置信息呢,看这里

aMap.setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
                @Override
                public void onCameraChange(CameraPosition cameraPosition) {

                    LatLng latLonPoint = marker.getOptions().getPosition();

                }

                @Override
                public void onCameraChangeFinish(CameraPosition cameraPosition) {
                    getAddressByLatlng(cameraPosition.target);
                }
            });

通过给地图的管理类添加地图移动时的监听器来实现,可以看到在地图移动结束的时候我们获取了移动结束时的经纬度, cameraPosition.target这个api获取的就是经纬度来的,然后我们通过它来获取位置信息

//通过经纬度获取地址
    private void getAddressByLatlng(LatLng latLng) {
        //逆地理编码查询条件:逆地理编码查询的地理坐标点、查询范围、坐标类型。
        LatLonPoint latLonPoint = new LatLonPoint(latLng.latitude, latLng.longitude);
        RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 2000f, GeocodeSearch.AMAP);
        //异步查询
        geocodeSearch.getFromLocationAsyn(query);
    }

没什么,传入经纬度发起搜索,然后,我们看回调方法

//通过经纬度查找地址的回调方法
    @Override
    public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
        RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();
        regeocodeResult.getRegeocodeAddress().getDistrict();
        String formatAddress = regeocodeAddress.getFormatAddress();
        String simpleAddress = formatAddress.substring(9);
        doSearchQuery(regeocodeResult.getRegeocodeAddress().getDistrict());
        fistLineData.setAddress(simpleAddress);
        fistLineData.setStreet(regeocodeAddress.getDistrict());
        // showToast("查询经纬度对应详细地址:\n" + simpleAddress);
    }

simpleAddress就是经纬度获取的信息了,regeocodeAddress 中还有其他的一些信息,但我不需要就不展开了。

doSearchQuery(regeocodeResult.getRegeocodeAddress().getDistrict());


通过这句,我们又发起了搜索,然后就是根据获取的数据去刷新列表,这就实现了位置的实时刷新了,至此,添加marker 定位 搜索
实时刷新的功能就实现了