前面两篇博客讲解了百度地图的使用、模式的切换以及定位,我们这篇博客来讲解一下百度地图覆盖物的添加。
地图 SDK 提供的点标记功能包含两大部分,一部分是点(俗称 Marker)、另一部分是浮于点上方的信息窗体(俗称 InfoWindow)。同时,SDK 对 Marker 和 InfoWindow 封装了大量的触发事件,例如点击事件、长按事件、拖拽事件。
效果图
要给地图添加覆盖物,首先需要覆盖物的经纬度,如果还要实现点击事件,显示详细的信息,还需要覆盖物的描述信息(如图片,位置名称等),所以先新建一个实体类,来存放这些信息。
实体类信息
public class Info implements Serializable {
private double latitude;
private double longtitude;
private int imgId;
private String name;
private String distance;
private int zan;
public static List<Info> infos=new ArrayList<>();
static
{
//添加几条markerinfo数据,用来显示marker
infos.add(new Info(34.242652, 108.971171, R.drawable.a01, "英伦贵族小旅馆",
"距离209米", 1456));
infos.add(new Info(34.242952, 108.972171, R.drawable.a02, "沙井国际洗浴会所",
"距离897米", 456));
infos.add(new Info(34.242852, 108.973171, R.drawable.a03, "五环服装城",
"距离249米", 1456));
infos.add(new Info(34.242152, 108.971971, R.drawable.a04, "老米家泡馍小炒",
"距离679米", 1456));
}
public Info(double latitude, double longtitude, int imgId, String name, String distance, int zan) {
this.latitude = latitude;
this.longtitude = longtitude;
this.imgId = imgId;
this.name = name;
this.distance = distance;
this.zan = zan;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongtitude() {
return longtitude;
}
public void setLongtitude(double longtitude) {
this.longtitude = longtitude;
}
public int getImgId() {
return imgId;
}
public void setImgId(int imgId) {
this.imgId = imgId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDistance() {
return distance;
}
public void setDistance(String distance) {
this.distance = distance;
}
public int getZan() {
return zan;
}
public void setZan(int zan) {
this.zan = zan;
}
}
添加Marker
具体实现代码如下:
//定义Maker坐标点
LatLng point = new LatLng(50.253647, 130.456321);
//构建Marker图标
BitmapDescriptor bitmap = BitmapDescriptorFactory
.fromResource(R.drawable.maker);
//构建MarkerOption,用于在地图上添加Marker
OverlayOptions option = new MarkerOptions()
.position(point)
.icon(bitmap);
//在地图上添加Marker,并显示
mBaiduMap.addOverlay(option);
添加文字和信息窗
文字(Text)和弹窗覆盖物(InfoWindow),在地图中也是一种覆盖物,可以使用showInfoWindow方法展示出来
具体代码实现方式如下:
TextView tv = new TextView(mContext);
tv.setBackgroundResource(R.drawable.location_tips);
tv.setPadding(30, 20, 30, 50);
tv.setText(info.getName());
tv.setTextColor(Color.parseColor("#ffffff"));
//定义用于显示该InfoWindow的坐标点
final LatLng latLng = marker.getPosition();
Point p = mBaiduMap.getProjection().toScreenLocation(latLng);
p.y -= 47;
LatLng ll = mBaiduMap.getProjection().fromScreenLocation(p);
infoWindow = new InfoWindow(tv, ll, -47);
mBaiduMap.showInfoWindow(infoWindow);
点击覆盖物显示详细信息
我们可以通过setOnMarkerClickListener点击事件获取到覆盖物的详细信息,具体实现代码如下:
mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
Bundle extraInfo = marker.getExtraInfo();
Info info = (Info) extraInfo.getSerializable("info");
ImageView mIvPhoto= (ImageView) mMarkerLy.findViewById(R.id.iv_photo);
TextView mTvName= (TextView) mMarkerLy.findViewById(R.id.tv_name);
TextView mTvDistance= (TextView) mMarkerLy.findViewById(R.id.tv_distance);
TextView mTvZan= (TextView) mMarkerLy. findViewById(R.id.tv_zan);
mIvPhoto.setImageResource(info.getImgId());
mTvName.setText(info.getName());
mTvDistance.setText(info.getDistance());
mTvZan.setText(info.getZan()+"");
InfoWindow infoWindow;
TextView tv = new TextView(mContext);
tv.setBackgroundResource(R.drawable.location_tips);
tv.setPadding(30, 20, 30, 50);
tv.setText(info.getName());
tv.setTextColor(Color.parseColor("#ffffff"));
//定义用于显示该InfoWindow的坐标点
final LatLng latLng = marker.getPosition();
Point p = mBaiduMap.getProjection().toScreenLocation(latLng);
p.y -= 47;
LatLng ll = mBaiduMap.getProjection().fromScreenLocation(p);
infoWindow = new InfoWindow(tv, ll, -47);
mBaiduMap.showInfoWindow(infoWindow);
mMarkerLy.setVisibility(View.VISIBLE);
return true;
}
});
主界面代码
下面总结一下MainActivity代码,包含地图模式控制,地图定位,带方向的定位,显示覆盖物,显示覆盖物点击事件等,希望大家多多指正。
public class MainActivity extends AppCompatActivity {
private MapView mMapView;
private BaiduMap mBaiduMap;
private MyLocationConfiguration.LocationMode mCurrentMode;
public LocationClient mLocationClient = null;
private MyLocationListener myListener ;
public static final int Location_Permission = 0x01;
boolean isFirstIn=true;
private double mLatitude;
private double mLongitude;
private BitmapDescriptor mIcon;
private Context mContext;
private MyOrientationListener mMMyOrientationListener;
private float mCurrentX;
//覆盖物相关
private BitmapDescriptor mMarkerBitmap;
private RelativeLayout mMarkerLy;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
this.mContext=this;
//声明LocationClient类
mLocationClient = new LocationClient(getApplicationContext());
myListener = new MyLocationListener();
//注册监听函数
mLocationClient.registerLocationListener(myListener);
mMMyOrientationListener=new MyOrientationListener(mContext);
initView();
if (Build.VERSION.SDK_INT >= 23){
requestLocalPermission();
}else{
initLocal();
}
initMarker();
mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
Bundle extraInfo = marker.getExtraInfo();
Info info = (Info) extraInfo.getSerializable("info");
ImageView mIvPhoto= (ImageView) mMarkerLy.findViewById(R.id.iv_photo);
TextView mTvName= (TextView) mMarkerLy.findViewById(R.id.tv_name);
TextView mTvDistance= (TextView) mMarkerLy.findViewById(R.id.tv_distance);
TextView mTvZan= (TextView) mMarkerLy. findViewById(R.id.tv_zan);
mIvPhoto.setImageResource(info.getImgId());
mTvName.setText(info.getName());
mTvDistance.setText(info.getDistance());
mTvZan.setText(info.getZan()+"");
InfoWindow infoWindow;
TextView tv = new TextView(mContext);
tv.setBackgroundResource(R.drawable.location_tips);
tv.setPadding(30, 20, 30, 50);
tv.setText(info.getName());
tv.setTextColor(Color.parseColor("#ffffff"));
//定义用于显示该InfoWindow的坐标点
final LatLng latLng = marker.getPosition();
Point p = mBaiduMap.getProjection().toScreenLocation(latLng);
p.y -= 47;
LatLng ll = mBaiduMap.getProjection().fromScreenLocation(p);
infoWindow = new InfoWindow(tv, ll, -47);
mBaiduMap.showInfoWindow(infoWindow);
mMarkerLy.setVisibility(View.VISIBLE);
return true;
}
});
mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener()
{
@Override
public boolean onMapPoiClick(MapPoi arg0)
{
return false;
}
@Override
public void onMapClick(LatLng arg0)
{
mMarkerLy.setVisibility(View.GONE);
mBaiduMap.hideInfoWindow();
}
});
}
/**
* 初始化覆盖物
*/
private void initMarker() {
mMarkerBitmap=BitmapDescriptorFactory.fromResource(R.drawable.maker);
mMarkerLy = (RelativeLayout) findViewById(R.id.rl_marker);
}
/**
* 定位到我的位置
*/
private void aboutLocal(){
MapStatusUpdate mapLatlng = MapStatusUpdateFactory.
newLatLng(new LatLng(mLatitude,mLongitude));
mBaiduMap.animateMapStatus(mapLatlng);
}
/**
* 初始化定位
*/
private void initLocal() {
LocationClientOption option = new LocationClientOption();
//可选,设置定位模式,默认高精度
//LocationMode.Hight_Accuracy:高精度;
//LocationMode. Battery_Saving:低功耗;
//LocationMode. Device_Sensors:仅使用设备;
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
//可选,设置返回经纬度坐标类型,默认gcj02
//gcj02:国测局坐标;
//bd09ll:百度经纬度坐标;
//bd09:百度墨卡托坐标;
//海外地区定位,无需设置坐标类型,统一返回wgs84类型坐标
option.setCoorType("bd09ll");
//可选,设置发起定位请求的间隔,int类型,单位ms
//如果设置为0,则代表单次定位,即仅定位一次,默认为0
//如果设置非0,需设置1000ms以上才有效
option.setScanSpan(1000);
//可选,设置是否使用gps,默认false
//使用高精度和仅用设备两种定位模式的,参数必须设置为true
option.setOpenGps(true);
//可选,设置是否当GPS有效时按照1S/1次频率输出GPS结果,默认false
option.setLocationNotify(true);
//可选,定位SDK内部是一个service,并放到了独立进程。
//设置是否在stop的时候杀死这个进程,默认(建议)不杀死,即setIgnoreKillProcess(true)
option.setIgnoreKillProcess(false);
//可选,设置是否收集Crash信息,默认收集,即参数为false
option.SetIgnoreCacheException(false);
//可选,7.2版本新增能力
//如果设置了该接口,首次启动定位时,会先判断当前WiFi是否超出有效期,若超出有效期,会先重新扫描WiFi,然后定位
option.setWifiCacheTimeOut(5*60*1000);
//可选,设置是否需要过滤GPS仿真结果,默认需要,即参数为false
option.setEnableSimulateGps(false);
//mLocationClient为第二步初始化过的LocationClient对象
//需将配置好的LocationClientOption对象,通过setLocOption方法传递给LocationClient对象使用
//更多LocationClientOption的配置,请参照类参考中LocationClientOption类的详细说明
option.setIsNeedAddress(true);
//自定义图标
mIcon=BitmapDescriptorFactory.fromResource(R.drawable.navi_map_gps_locked);
mLocationClient.setLocOption(option);
mMMyOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
@Override
public void onOrientationChanged(float x) {
mCurrentX=x;
}
});
// mBaiduMap.setMyLocationEnabled(true);
// if (!mLocationClient.isStarted()){
// mLocationClient.start();
// }
// //开始方向传感器
// mMMyOrientationListener.start();
}
private void initView() {
mMapView = (MapView) findViewById(R.id.mv_map);
mBaiduMap = mMapView.getMap();
//放大地图的倍数
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f);
mBaiduMap.setMapStatus(msu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.id_map_common: //普通地图
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
break;
case R.id.id_map_site: //卫星地图
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
break;
case R.id.id_map_none: //空白地图
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);
break;
case R.id.id_map_traffic: //实时交通(off)
if (mBaiduMap.isTrafficEnabled())
{
mBaiduMap.setTrafficEnabled(false);
item.setTitle("实时交通(off)");
} else
{
mBaiduMap.setTrafficEnabled(true);
item.setTitle("实时交通(on)");
}
break;
case R.id.id_map_location: //我的位置
aboutLocal();
break;
case R.id.id_map_mode_common: //普通模式
mCurrentMode = MyLocationConfiguration.LocationMode.NORMAL; //默认为 LocationMode.NORMAL 普通态
break;
case R.id.id_map_mode_following: //跟随模式
mCurrentMode = MyLocationConfiguration.LocationMode.FOLLOWING;//定位跟随态
break;
case R.id.id_map_mode_compass: //罗盘模式
mCurrentMode = MyLocationConfiguration.LocationMode.COMPASS; //定位罗盘态
break;
case R.id.id_add_overlay: //添加覆盖物
addOverlays(Info.infos);
break;
}
return super.onOptionsItemSelected(item);
}
/**
* 添加覆盖物
* @param infos
*/
private void addOverlays(List<Info> infos) {
mBaiduMap.clear();
LatLng latLng=null;
Marker marker=null;
OverlayOptions options;
for (Info info:infos){
//经纬度
latLng=new LatLng(info.getLatitude(),info.getLongtitude());
//图标
options=new MarkerOptions().position(latLng).icon(mMarkerBitmap).zIndex(5);
marker= (Marker) mBaiduMap.addOverlay(options);
Bundle bundle=new Bundle();
bundle.putSerializable("info",info);
marker.setExtraInfo(bundle);
}
MapStatusUpdate msu=MapStatusUpdateFactory.newLatLng(latLng);
mBaiduMap.animateMapStatus(msu);
}
@Override
protected void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
protected void onStart() {
super.onStart();
mBaiduMap.setMyLocationEnabled(true);
if (!mLocationClient.isStarted()){
mLocationClient.start();
}
//开始方向传感器
mMMyOrientationListener.start();
}
@Override
protected void onStop() {
super.onStop();
mBaiduMap.setMyLocationEnabled(false);
mLocationClient.stop();
//停止方向传感器
mMMyOrientationListener.stop();
}
class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation bdLocation) {
//此处的BDLocation为定位结果信息类,通过它的各种get方法可获取定位相关的全部结果
//以下只列举部分获取经纬度相关(常用)的结果信息
//更多结果信息获取说明,请参照类参考中BDLocation类中的说明
double latitude = bdLocation.getLatitude(); //获取纬度信息
double longitude = bdLocation.getLongitude(); //获取经度信息
float radius = bdLocation.getRadius(); //获取定位精度,默认值为0.0f
// String coorType = bdLocation.getCoorType();
// MapStatusUpdate mapUpdate = MapStatusUpdateFactory.zoomTo(radius);
// mBaiduMap.setMapStatus(mapUpdate);
MyLocationData data = new MyLocationData.Builder()//
.direction(mCurrentX)//
.accuracy(radius)//
.latitude(latitude)//
.longitude(longitude)//
.build();
mBaiduMap.setMyLocationData(data);
//设置自定义图标
mBaiduMap.setMyLocationConfiguration(new MyLocationConfiguration(
mCurrentMode, true, mIcon));
//更新经纬度
mLatitude= bdLocation.getLatitude();
mLongitude=bdLocation.getLongitude();
LatLng point= new LatLng(latitude,longitude);
if (isFirstIn){
//开始移动
MapStatusUpdate mapLatlng = MapStatusUpdateFactory.
newLatLng(point);
mBaiduMap.animateMapStatus(mapLatlng);
Toast.makeText(mContext,bdLocation.getAddrStr(), Toast.LENGTH_SHORT).show();
isFirstIn=false;
}
// //绘制图层
// //定义Maker坐标点
// LatLng point = new LatLng(latitude,longitude);
// //构建Marker图标
// BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_gcoding);
// //构建MarkerOption,用于在地图上添加Marker
// OverlayOptions option = new MarkerOptions().position(point).icon(bitmap);
// //在地图上添加Marker,并显示
// mBaiduMap.addOverlay(option);
}
}
private void requestLocalPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
//若权限没有开启,则请求权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, Location_Permission);
}else{
initLocal();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode==Location_Permission){
if (grantResults[0]==PackageManager.PERMISSION_GRANTED){
initLocal();
}else{
Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
}
return;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
到这里覆盖物的添加就已经讲解就基本完了,代码是根据鸿洋大神的视频修改的,有需要的话可以去我的资源里面进行下载。关于百度地图的基本使用到此就结束了,有说的不好的地方请大家多多指正。
Demo