归纳下最近做的仿微信地理位置选择,T^T。避免下次再遇上类似功能需求又得重新去看高德开发文档。(此次这下本文也是基于本人刚删完代码就遇上需求,又重新看了一遍开发文档)。
先上效果图:
本文使用的是高德地图,jar包如下图,若高德以后更新版本可能会有些方法改变,所以本文只只对当前版本。
接下来归纳下本文所使用功能。
1.地图(这是必须的)
2.定位
3.添加标注(mark)
4.poi索引(地图下面的列表,PoiSearch)
5.逆地理编码(坐标转地址,用于移动地图后poi检索出周边,GeocodeSearch)
ok大概就这些了。
接下来上布局预览:
,这里的重新定位是自己定义的一个按钮,并不是用地图自带的(自带的在地图的右上角),自定义的原因是自己之前封装好了一个定位,这里只要重新调用就行,纯属为了自己方便
地图跟定位是相对简单的,这里就不介绍了,
定位后把地图移动到当前地理位置,
重点看POI 和地理的逆编码
下面上一张poiItems的返回参数图,供参考
地理的逆编码:
只需传入经纬度,范围,第三个参数表示是火系坐标系还是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);
}}