美文网首页Android知识库今日看点Android开发
Android 仿微信发送地理位置地图

Android 仿微信发送地理位置地图

作者: 无灬痕 | 来源:发表于2016-12-01 10:49 被阅读2096次

    归纳下最近做的仿微信地理位置选择,T^T。避免下次再遇上类似功能需求又得重新去看高德开发文档。(此次这下本文也是基于本人刚删完代码就遇上需求,又重新看了一遍开发文档)。

    先上效果图:

    GIF.gif

    本文使用的是高德地图,jar包如下图,若高德以后更新版本可能会有些方法改变,所以本文只只对当前版本。


    850085424713306039.jpg

    接下来归纳下本文所使用功能。

    1.地图(这是必须的)

    2.定位

    3.添加标注(mark)

    4.poi索引(地图下面的列表,PoiSearch)

    5.逆地理编码(坐标转地址,用于移动地图后poi检索出周边,GeocodeSearch)

    ok大概就这些了。

    接下来上布局预览:

    Paste_Image.png

    ,这里的重新定位是自己定义的一个按钮,并不是用地图自带的(自带的在地图的右上角),自定义的原因是自己之前封装好了一个定位,这里只要重新调用就行,纯属为了自己方便

    地图跟定位是相对简单的,这里就不介绍了,

    定位后把地图移动到当前地理位置,

    Paste_Image.png

    重点看POI 和地理的逆编码

    Paste_Image.png

    下面上一张poiItems的返回参数图,供参考

    Paste_Image.png

    地理的逆编码:

    Paste_Image.png

    只需传入经纬度,范围,第三个参数表示是火系坐标系还是GPS原生坐标系(具体的参考开发文档)

    OK ,至此地图+地理列表页完成,剩下的就是手动输入地址检索出附近地址列表了(poi)因为这里已有类似代码,就不再介绍。

    附送源码:
    地图+列表选择页

    public class MapLocationActivity extends BaseActivity {
    private TextView tvTitle, tvBack;
    private LinearLayout llBack;
    private MapView mMapView;
    private AMap aMap;
    private UiSettings mUiSettings;
    
    private ImageView ivLocation;
    
    private PoiSearch.Query poiquery;
    private RecyclerView recyclerView;
    private LoactionAddressAdapter loactionAddressAdapter;
    private List<LocationAddress> locationAddressList;
    
    private TextView tvSearch;
    private Marker marker;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map_location);
        mMapView = getView(R.id.gs_map);
        //在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),实现地图生命周期管理
        mMapView.onCreate(savedInstanceState);
        initView();
        initListener();
    }
    
    private void initListener() {
        //监测地图画面的移动
        aMap.setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
            @Override
            public void onCameraChangeFinish(CameraPosition cameraPosition) {
                //     ToastUtil.showToast(getApplicationContext(), cameraPosition.target.longitude+"当前地图中心位置: "+cameraPosition.target.latitude);
                //addMark(cameraPosition.target.latitude,cameraPosition.target.longitude);
                latSearchList(cameraPosition.target.latitude, cameraPosition.target.longitude);
    
            }
    
            @Override
            public void onCameraChange(CameraPosition cameraPosition) {
            }
        });
        //是否显示地图中放大缩小按钮
        mUiSettings.setZoomControlsEnabled(false);
        mUiSettings.setMyLocationButtonEnabled(false); // 是否显示默认的定位按钮
        aMap.setMyLocationEnabled(false);// 是否可触发定位并显示定位层
    
        //不设置触摸地图的时候会报错
        aMap.setOnMapClickListener(new AMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
    
            }
        });
        ivLocation.setOnClickListener(onClickListener);
        llBack.setOnClickListener(onClickListener);
        tvSearch.setOnClickListener(onClickListener);
        loactionAddressAdapter.setItemListener(new LoactionAddressAdapter.OnItemListener() {
            @Override
            public void onItemClick(int position, RecyclerView.ViewHolder viewHolder) {
    
                Intent data = new Intent();
                data.putExtra("data", locationAddressList.get(position).getPoiItem());
                setResult(RESULT_OK, data);
                finish();
    
            }
        });
    }
    
    private void initView() {
        tvTitle = getView(R.id.tv_top_title_center);
        tvBack = getView(R.id.tv_title_left);
        tvBack.setVisibility(View.VISIBLE);
        llBack = getView(R.id.ll_title_left);
        tvSearch = getView(R.id.tv_search);
        ivLocation = getView(R.id.iv_loaction);
        if (aMap == null) {
            aMap = mMapView.getMap();
            mUiSettings = aMap.getUiSettings();
        }
        aMap.setTrafficEnabled(true);// 显示实时交通状况
        //地图模式可选类型:MAP_TYPE_NORMAL,MAP_TYPE_SATELLITE,MAP_TYPE_NIGHT
        aMap.setMapType(AMap.MAP_TYPE_NORMAL);//
    
        recyclerView = getView(R.id.map_recyler);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        locationAddressList = new ArrayList<>();
        loactionAddressAdapter = new LoactionAddressAdapter(this, locationAddressList);
        recyclerView.setAdapter(loactionAddressAdapter);
    
        tvTitle.setText("位置");
        location();
    
    }
    
    //定位
    private void location() {
        GooleMapUtils.getInstence().init(this, new GooleMapUtils.GetGooleMapListener() {
            @Override
            public void onMapListener(String cityName, AMapLocation aMapLocation, boolean location) {
                if (true) {
                    if (!TextUtils.isEmpty(aMapLocation.getCityCode()) && !TextUtils.isEmpty(aMapLocation.getRoad())) {
                        searchList(aMapLocation.getCityCode(), aMapLocation.getRoad());
                        //把地图移动到定位地点
                        moveMapCamera(aMapLocation.getLatitude(), aMapLocation.getLongitude());
                        addmark(aMapLocation.getLatitude(), aMapLocation.getLongitude());
                    }
                } else {
                    ToastUtil.showToast(MapLocationActivity.this, "定位失败");
                }
            }
        });
    }
    
    //把地图画面移动到定位地点
    private void moveMapCamera(double latitude, double longitude) {
        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 14));
    }
    
    private void addmark(double latitude, double longitude) {
    
        if (marker == null) {
            marker = aMap.addMarker(new MarkerOptions()
                    .position(new LatLng(latitude, longitude))
                    .icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory
                            .decodeResource(getResources(), R.mipmap.myselfe_location_icon)))
                    .draggable(true));
        } else {
            marker.setPosition(new LatLng(latitude, longitude));
            aMap.invalidate();
        }
    
    
    }
    
    //poi搜索
    private void searchList(String cityCode, String road) {
        if (TextUtils.isEmpty(road)) {
            locationAddressList.clear();
            loactionAddressAdapter.notifyDataSetChanged();
        }
        poiquery = new PoiSearch.Query(road, "", cityCode);
        poiquery.setPageSize(15);
        poiquery.setPageNum(2);
        PoiSearch poiSearch = new PoiSearch(this, poiquery);
        poiSearch.setOnPoiSearchListener(onPoiSearchListener);
        poiSearch.searchPOIAsyn();
    }
    
    private void latSearchList(double latitude, double longitude) {
        //设置周边搜索的中心点以及半径
        GeocodeSearch geocodeSearch = new GeocodeSearch(this);
        //地点范围500米
        RegeocodeQuery query = new RegeocodeQuery(new LatLonPoint(latitude, longitude), 500, GeocodeSearch.AMAP);
    
        geocodeSearch.getFromLocationAsyn(query);
    
        geocodeSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() {
            @Override
            public void onRegeocodeSearched(RegeocodeResult result, int rCode) {
                if (rCode == 1000) {
                    if (result != null && result.getRegeocodeAddress() != null
                            && result.getRegeocodeAddress().getFormatAddress() != null) {
                      /* String addressName = result.getRegeocodeAddress().getFormatAddress()
                                + "附近";
                        Log.v("sssssssss","ssssssssssssss"+addressName);*/
                        searchList(result.getRegeocodeAddress().getCityCode(), result.getRegeocodeAddress().getTownship());
                    }
                }
            }
    
            @Override
            public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {
            }
        });
    
    }
    
    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.iv_loaction:
                    location();
                    break;
                case R.id.ll_title_left:
                    finish();
                    break;
                case R.id.tv_search:
                    Intent intent = new Intent();
                    intent.setClass(MapLocationActivity.this, LocationActivity.class);
                    startActivityForResult(intent, 1);
                    break;
    
            }
        }
    };
    
    //索引搜索
    PoiSearch.OnPoiSearchListener onPoiSearchListener = new PoiSearch.OnPoiSearchListener() {
        @Override
        public void onPoiSearched(PoiResult result, int rCode) {
            if (rCode == 1000) {
                if (result != null && result.getQuery() != null) {// 搜索poi的结果
                    if (result.getQuery().equals(poiquery)) {// 是否是同一条
                        //     poiResult = result;
                        // 取得搜索到的poiitems有多少页
                        List<PoiItem> poiItems = result.getPois();// 取得第一页的poiitem数据,页数从数字0开始
                        List<SuggestionCity> suggestionCities = result
                                .getSearchSuggestionCitys();// 当搜索不到poiitem数据时,会返回含有搜索关键字的城市信息
                        locationAddressList.clear();
                        if (poiItems != null && poiItems.size() > 0) {
                            for (int i = 0; i < poiItems.size(); i++) {
                                LocationAddress locationAddress = new LocationAddress();
                                locationAddress.setPoiItem(poiItems.get(i));
                                locationAddressList.add(locationAddress);
                            }
                         /*   if (isSearch){
                                    moveMapCamera(poiItems.get(0).getLatLonPoint().getLatitude(),poiItems.get(0).getLatLonPoint().getLongitude());
                            }*/
                        }
                        loactionAddressAdapter.notifyDataSetChanged();
                    }
                }
            }
        }
    
        @Override
        public void onPoiItemSearched(PoiItem poiItem, int i) {
    
        }
    };
    
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
        mMapView.onDestroy();
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        //在activity执行onResume时执行mMapView.onResume (),实现地图生命周期管理
        mMapView.onResume();
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        //在activity执行onPause时执行mMapView.onPause (),实现地图生命周期管理
        mMapView.onPause();
    }
    
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        //在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),实现地图生命周期管理
        mMapView.onSaveInstanceState(outState);
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1) {
            if (resultCode == RESULT_OK) {
                if (data != null) {
                    // 获取返回的数据
                    PoiItem poiItem = (PoiItem) data.getParcelableExtra("data");
                    // 处理自己的逻辑 ....
                    searchList(poiItem.getCityCode(), poiItem.getBusinessArea());
                    moveMapCamera(poiItem.getLatLonPoint().getLatitude(), poiItem.getLatLonPoint().getLongitude());
                }
    
            }
        }
    }}
    

    手动输入POI索引页:

    public class LocationActivity extends BaseActivity {
    private PoiSearch.Query poiquery;
    private EditText etSearch;
    private RecyclerView recyclerView;
    private LoactionAddressAdapter loactionAddressAdapter;
    private List<LocationAddress> locationAddressList;
    private String code;
    private LinearLayout llBack;
    private TextView tvTitle,tvBack;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
    
        initView();
        initData();
        initListener();
    }
    
    private void initListener() {
        loactionAddressAdapter.setItemListener(new LoactionAddressAdapter.OnItemListener() {
            @Override
            public void onItemClick(int position, RecyclerView.ViewHolder viewHolder) {
                Intent data = new Intent();
                data.putExtra("data", locationAddressList.get(position).getPoiItem());
                setResult(RESULT_OK, data);
                finish();
            }
        });
    }
    
    private void initData() {
        tvBack.setVisibility(View.VISIBLE);
        tvTitle.setText("位置");
        GooleMapUtils.getInstence().init(this, new GooleMapUtils.GetGooleMapListener() {
            @Override
            public void onMapListener(String cityName, AMapLocation aMapLocation, boolean location) {
                if (true){
                    if (!TextUtils.isEmpty(aMapLocation.getCityCode())&&!TextUtils.isEmpty(aMapLocation.getRoad())){
                        code =aMapLocation.getCityCode();
                        searchList(aMapLocation.getCityCode(),aMapLocation.getRoad());
                    }
                }else {
                    ToastUtil.showToast(LocationActivity.this,"定位失败");
                }
            }
        });
    
        etSearch.addTextChangedListener(textWatcher);
    }
    TextWatcher textWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }
    
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
    
        }
    
        @Override
        public void afterTextChanged(Editable s) {
            searchList(code,etSearch.getText().toString().trim());
        }
    };
    
    private void initView() {
        tvTitle = getView(R.id.tv_top_title_center);
        tvBack = getView(R.id.tv_title_left);
        llBack = getView(R.id.ll_title_left);
        etSearch = getView(R.id.et_search);
        recyclerView = getView(R.id.search_list);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        locationAddressList = new ArrayList<>();
        loactionAddressAdapter = new LoactionAddressAdapter(this,locationAddressList);
        recyclerView.setAdapter(loactionAddressAdapter);
    
        llBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
    
    private void searchList(String cityCode, String road) {
        if (TextUtils.isEmpty(road)){
            locationAddressList.clear();
            loactionAddressAdapter.notifyDataSetChanged();
        }
        poiquery = new PoiSearch.Query(road,"",cityCode);
        poiquery.setPageSize(15);
        poiquery.setPageNum(2);
        PoiSearch poiSearch = new PoiSearch(this,poiquery);
        poiSearch.setOnPoiSearchListener(onPoiSearchListener);
        poiSearch.searchPOIAsyn();
    }
    
    
    //索引搜索
    PoiSearch.OnPoiSearchListener onPoiSearchListener = new PoiSearch.OnPoiSearchListener() {
        @Override
        public void onPoiSearched(PoiResult result, int rCode) {
            if (rCode == 1000) {
                if (result != null && result.getQuery() != null) {// 搜索poi的结果
                    if (result.getQuery().equals(poiquery)) {// 是否是同一条
                   //     poiResult = result;
                        // 取得搜索到的poiitems有多少页
                        List<PoiItem> poiItems = result.getPois();// 取得第一页的poiitem数据,页数从数字0开始
                        List<SuggestionCity> suggestionCities = result
                                .getSearchSuggestionCitys();// 当搜索不到poiitem数据时,会返回含有搜索关键字的城市信息
                        locationAddressList.clear();
                        if (poiItems != null && poiItems.size() > 0) {
                            for (int i=0;i<poiItems.size();i++){
                                LocationAddress locationAddress = new LocationAddress();
                                locationAddress.setPoiItem(poiItems.get(i));
                                locationAddressList.add(locationAddress);
                            }
                        }
                        loactionAddressAdapter.notifyDataSetChanged();
                    }
                }
            }
        }
        @Override
        public void onPoiItemSearched(PoiItem poiItem, int i) {
    
        }
    };}
    

    定位:

    public class GooleMapUtils {
    
    //声明AMapLocationClient类对象
    public AMapLocationClient mLocationClient = null;
    //声明定位回调监听器
    public AMapLocationListener mLocationListener;
    
    //声明mLocationOption对象
    public AMapLocationClientOption mLocationOption = null;
    
    public static GooleMapUtils amap;
    private GetGooleMapListener getGooleMapListener1;
    private boolean isfirst=true;
    private Context context;
    
    public static GooleMapUtils getInstence() {
        if (amap == null) {
            amap = new GooleMapUtils();
        }
        return amap;
    }
    
    public void init(final Context context ,GetGooleMapListener getGooleMapListener) {
    
        this.context =context;
        this.getGooleMapListener1=getGooleMapListener;
        mLocationListener = new AMapLocationListener() {
            @Override
            public void onLocationChanged(AMapLocation aMapLocation) {
    
           //    Log.v("sssssss","sssssss这个是地区id  比如海珠区"+aMapLocation);
                    if (aMapLocation != null && aMapLocation.getErrorCode() == 0) {
                        if (getGooleMapListener1!=null)
                        getGooleMapListener1.onMapListener(aMapLocation.getCity(),aMapLocation,true);
                        
    
                    } else {
                        if (getGooleMapListener1!=null)
                        getGooleMapListener1.onMapListener("定位失败", null,false);
                    }
    
            }
        };
        mLocationClient = new AMapLocationClient(context);
        //设置定位回调监听
        mLocationClient.setLocationListener(mLocationListener);
    
        mLocationOption = new AMapLocationClientOption();
    
        //设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        //设置是否返回地址信息(默认返回地址信息)
        mLocationOption.setNeedAddress(true);
        //设置是否只定位一次,默认为false
        mLocationOption.setOnceLocation(true);
        //设置是否强制刷新WIFI,默认为强制刷新
        mLocationOption.setWifiActiveScan(true);
        //设置是否允许模拟位置,默认为false,不允许模拟位置
        mLocationOption.setMockEnable(false);
        //设置定位间隔,单位毫秒,默认为2000ms
        mLocationOption.setInterval(30*60*1000);
        //给定位客户端对象设置定位参数
        mLocationClient.setLocationOption(mLocationOption);
        //启动定位
        mLocationClient.startLocation();
    }
    
    public interface GetGooleMapListener{
    
        void onMapListener(String cityName, AMapLocation  aMapLocation,boolean location);
    }}

    相关文章

      网友评论

      • wodezhzh:大神你能把布局或者dome发下吗?
        无灬痕:这个是我从项目中抽出来的。没有demo, 布局的话,文中有预览图,大概是上半部分是map 下半部分是rv.
      • OliverBuddy:项目中正好需要这个功能,学习了,思路清晰了,谢谢:kissing_heart:
        无灬痕:@OliverBuddy :smiley: 能帮到你就好。
      • BandaYung:有Demo吗,发个链接我
        无灬痕:@ShaoLin :cry: 这个没有demo 我是直接从项目中整理出来的,上面的代码除了封装好的定位,已经包含两个界面的代码啦。我把定位部分的代码也更新上去吧

      本文标题:Android 仿微信发送地理位置地图

      本文链接:https://www.haomeiwen.com/subject/cprxmttx.html