最近项目要接入地图定位,选择位置的功能,乙方用了百度地图,记录一下使用过程。
功能:
可以拖动marker改变定位位置;
点击POI列表对象,mark移动到相应位置;
点击定位回到当前位置。
ps: 搜索功能暂时没需要就没加,也比较简单。
目录
一、开发者平台使用
一、申请ak
二、添加相应jar包和so文件
二、定位代码实现
一、xml布局
二、recyc
目录
一、开发者平台使用
一、申请ak
二、添加相应jar包和so文件
二、定位代码实现
一、xml布局
二、activity实现
三、recycleadapter
leadapter
三、activity实现
注册个百度地图开放平台的账号,创建一个应用 http://lbsyun.baidu.com/
SHA1值的生成,参考这个百度地图论坛置顶的帖子:
http://bbs.lbsyun.baidu.com/forum.php?mod=viewthread&tid=106461&highlight=230
去开发者平台上下载需要的包,复制到AS里面:
我选了定位,地图和搜索的3个包,引入搜索包是因为,BaiduMap对象的点击事件监听接口的数据是经纬度对象,
用百度地图提供的GeoCoder类,可以根据经纬度查找返回地址,POI,经纬度等信息。
复制到项目里面:
把jar包作为项目依赖添加:
File --> Project Structure -->选中app 的dependence,点击 + 号,选中BaiduLBS_Android.jar 包,即可把此jar包添加为项目依赖,上图里面jar文件也出现三角号,可以点开查看了。
把libs 文件添加进依赖:
repositories {
flatDir {
dirs 'libs'
}
}
我用MVP模式写的,其实不是标准的mvp,逻辑和数据处理放在presenter里面了,没有用model进行数据处理。
/**
* 百度地图定位 contract
*/
public interface MapViewContract {
interface View extends BusinessView {
void showAddr(ReverseGeoCodeResult result);
}
abstract class Presenter extends BusinessPresenter {
public Presenter(BusinessActivity activity, View view) {
super(activity, view);
}
//将mapView对象传过来,用来实例化BaiduMap对象
public abstract void getAddr(MapView mMapView);
public abstract void backToCurrentLocation();//回到当前位置
public abstract void setMarkLocation(LatLng latLng);//设置marker位置
}
}
/**
* 可拖动 marker 定位
*/
public class MapViewActivity extends BusinessActivity implements MapViewContract.View, View.OnClickListener, LocationItemAdapter.onItemClickListener {
private MapView mMapView;
private TextView tvAddr;
private String locationAdrr = "";
private LinearLayout myLocation;
private RecyclerView searchListRecycle;
private LocationItemAdapter adapter;
private List poiInfoList = new ArrayList<>();
private double longitude;
private double latitude;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_view);
new MapViewPresenter(this, this);
setTitle("选择位置");
showAheadLayout();
getAheadTextView().setText("确定");
initView();
}
private void initView() {
mMapView = (MapView) findViewById(R.id.mapView);
tvAddr = (TextView) findViewById(R.id.tv_addr);
getPresenter().getAddr(mMapView);
myLocation = (LinearLayout) findViewById(R.id.my_location);
myLocation.setOnClickListener(this);
searchListRecycle = (RecyclerView) findViewById(R.id.search_list);
adapter = new LocationItemAdapter();
adapter.setItemList(poiInfoList);
adapter.setListener(this);
searchListRecycle.setLayoutManager(new LinearLayoutManager(this));
searchListRecycle.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
searchListRecycle.setAdapter(adapter);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.my_location:
//marker回到当前位置
getPresenter().backToCurrentLocation();
break;
}
}
//点击确定,返回定位的结果
@Override
public void onBarItemClick(ToolBarButton id) {
if (id == ToolBarButton.AHEAD) {
Intent intent = new Intent();
intent.putExtra(KeyName.ADDR_NAME, locationAdrr);
intent.putExtra(KeyName.ADDR_NAME_longitude,longitude);
intent.putExtra(KeyName.ADDR_NAME_latitude,latitude);
setResult(IntentCode.RESULT_ADDR_NAME, intent);
finish();
}
super.onBarItemClick(id);
}
@Override
protected void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
protected void onDestroy() {
mMapView.onDestroy();
mMapView = null;
super.onDestroy();
}
//获取到定位信息和周围POI,返回结果,view展示数据
@Override
public void showAddr(ReverseGeoCodeResult result) {
tvAddr.setText(result.getAddress());
locationAdrr = result.getAddress();
longitude = result.getLocation().longitude;
latitude = result.getLocation().latitude;
this.poiInfoList = result.getPoiList();
adapter.setItemList(poiInfoList);
adapter.notifyDataSetChanged();
}
//点击POI列表的对象,更新数据,设置marker位置
@Override
public void onItemClick(PoiInfo data, int position) {
if (null != data) {
tvAddr.setText(data.address);
locationAdrr = data.address;
longitude = data.location.longitude;
latitude = data.location.latitude;
getPresenter().setMarkLocation(data.location);
}
}
}
/**
* 百度地图定位 presenter
*/
public class MapViewPresenter extends MapViewContract.Presenter implements OnGetGeoCoderResultListener, OnGetPoiSearchResultListener {
private BaiduMap mBaiduMap = null;
private MyLocationData locData; //定位数据包
private Marker marker;//位置标志
boolean isFirstLoc = true; // 是否首次定位
LocationClient mLocClient;
GeoCoder mSearch = null; // 搜索模块,根据经纬度获取位置信息,也可去掉地图模块独立使用
PoiSearch mPoiSearch;//搜索附近POI,可用于根据关键字搜索位置
public MapViewPresenter(BusinessActivity activity, MapViewContract.View view) {
super(activity, view);
}
@Override
public void getAddr(MapView mMapView) {
mBaiduMap = mMapView.getMap();
//设置类型
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomTo(18f));
// 开启定位图层
mBaiduMap.setMyLocationEnabled(true);
//用application对象初始化LocationClient 对象
mLocClient = new LocationClient(getActivity().getApplicationContext());
//设置位置监听器
mLocClient.registerLocationListener(listener);
LocationClientOption option = new LocationClientOption();
option.setIsNeedAddress(true);//是否要地址
option.setOpenGps(true);
option.setCoorType("bd09ll"); // 设置坐标类型
//设置定位模式:高精度,低功耗,仅设备
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
//可选,默认0,即仅定位一次,设置发起连续定位请求的间隔需要大于等于1000ms才是有效的
option.setScanSpan(3000);
mLocClient.setLocOption(option);
mLocClient.start();
//对Marker的点击事件
mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
//获取marker中的数据
searchNearBy(marker.getPosition());
return false;
}
});
//Map点击事件,点击地图移动marker
mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
//设置marker位置,将marker移动到点击地图位置
marker.setPosition(latLng);
//反Geo搜索,根据经纬度搜索位置和POI信息
searchNearBy(marker.getPosition());
}
@Override
public boolean onMapPoiClick(MapPoi mapPoi) {
//同上
marker.setPosition(mapPoi.getPosition());
searchNearBy(marker.getPosition());
return false;
}
});
//对Marker的拖拽事件
mBaiduMap.setOnMarkerDragListener(new BaiduMap.OnMarkerDragListener() {
@Override
public void onMarkerDrag(Marker marker) {
}
@Override
public void onMarkerDragEnd(Marker marker) {
//根据经纬度获取位置和POI信息
searchNearBy(marker.getPosition());
}
@Override
public void onMarkerDragStart(Marker marker) {
}
});
// 初始化搜索模块,注册事件监听
mSearch = GeoCoder.newInstance();
mSearch.setOnGetGeoCodeResultListener(this);
//初始化POI搜索对象,可根据关键字搜索地址,但是此处我没有使用它
mPoiSearch = PoiSearch.newInstance();
mPoiSearch.setOnGetPoiSearchResultListener(this);
}
//点击回到当前位置
@Override
public void backToCurrentLocation() {
mLocClient.start();
}
//点击POI列表的item,对应移动marker到相应位置
@Override
public void setMarkLocation(LatLng latLng) {
if (null != marker) {
marker.setPosition(latLng);
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(latLng).zoom(18.0f);
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
}
}
/***
* 定位结果回调,在此方法中处理定位结果
*/
BDAbstractLocationListener listener = new BDAbstractLocationListener() {
@Override
public void onReceiveLocation(BDLocation bdLocation) {
// map view 销毁后不在处理新接收的位置
if (mLocClient == null || null == bdLocation) {
return;
}
//构造定位数据
locData = new MyLocationData.Builder()
.accuracy(bdLocation.getRadius())
.latitude(bdLocation.getLatitude())
.longitude(bdLocation.getLongitude())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100)
.build();
mBaiduMap.setMyLocationData(locData);
LatLng ll = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(ll).zoom(18.0f);
//更新地图状态
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
//根据经纬度搜索地址和POI信息
searchNearBy(ll);
//只有第一次定位的时候,构造marker对象
if (isFirstLoc) {
isFirstLoc = false;
BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.mipmap.locationmark);
// 构建MarkerOption,用于在地图上添加Marker
OverlayOptions option = new MarkerOptions()
.position(ll) //mark出现的位置
.icon(bitmap) //mark图标
.draggable(true);//mark可拖动
//在地图上添加Marker并显示
marker = (Marker) mBaiduMap.addOverlay(option);
} else {
//不是第一次定位,设置marker移动到当前定位的位置
if (null != marker) {
marker.setPosition(ll);
}
}
mLocClient.stop();
}
};
//根据经纬度,用GeoCoder 对象反geo编码获取到位置信息
public void searchNearBy(LatLng latLng) {
if (null != latLng) {
mSearch.reverseGeoCode(new ReverseGeoCodeOption()
.location(latLng));
} else {
ToastUtil.toast("未找到结果");
}
}
//反geo搜索的 OnGetGeoCodeResultListener返回数据接口
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
ToastUtil.toast("未能找到结果");
return;
}
getView().showAddr(result);
}
//geo搜索的 OnGetGeoCodeResultListener返回数据接口,此处用不到
@Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
}
@Override
public void onDestroy() {
super.onDestroy();
//退出时销毁定位
mLocClient.stop();
//退出时关闭定位图层
mBaiduMap.setMyLocationEnabled(false);
mSearch.destroy();
}
/**
* 通过经纬度 和 关键字 搜索poi,此处没有用到
*
* @param latLng
*/
private void search(LatLng latLng, String name) {
if (null != name) {
mPoiSearch.searchNearby(new PoiNearbySearchOption().keyword(name)
.location(latLng).radius(500).pageNum(1));
} else {
ToastUtil.toast("未找到结果");
//view 的POI列表显示空
}
}
//mPoiSearch.setOnGetPoiSearchResultListener监听器返回数据接口,此处没用到
//可用于关键字搜索位置信息和POI信息
@Override
public void onGetPoiResult(PoiResult poiResult) {
if (poiResult == null || poiResult.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {
ToastUtil.toast("未找到结果");
return;
}
if (poiResult.error == SearchResult.ERRORNO.NO_ERROR) {
ToastUtil.toast("poi 数目:" + poiResult.getAllPoi().size());
return;
}
}
@Override
public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
}
@Override
public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {
}
}
/**
* 百度地图定位,显示POI
*/
public class LocationItemAdapter extends RecyclerView.Adapter implements View.OnClickListener {
private List itemList;
private onItemClickListener listener;
private int position;
public void setListener(onItemClickListener listener) {
this.listener = listener;
}
public void setItemList(List itemList) {
this.itemList = itemList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_map_location, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.tvName.setText(itemList.get(position).name);
holder.tvAddress.setText(itemList.get(position).address);
holder.itemView.setTag(itemList.get(position));
this.position = position;
holder.rootView.setOnClickListener(this);
}
@Override
public int getItemCount() {
if (null != itemList) {
return itemList.size();
}
return 0;
}
@Override
public void onClick(View v) {
PoiInfo data = (PoiInfo) v.getTag();
if (null != data && null != listener) {
listener.onItemClick(data, position);
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public View rootView;
public TextView tvName;
public TextView tvAddress;
public ViewHolder(View rootView) {
super(rootView);
this.rootView = rootView;
this.tvName = (TextView) rootView.findViewById(R.id.tv_name);
this.tvAddress = (TextView) rootView.findViewById(R.id.tv_address);
}
}
public interface onItemClickListener {
void onItemClick(PoiInfo data, int position);
}
}
注:手势操作管理
UiSettings settings=mBaiduMap.getUiSettings();
settings.setAllGesturesEnabled(false); //关闭一切手势操作
settings.setZoomGesturesEnabled(false);//是否允许缩放手势