前言
前文介绍百度地图添加Marker的使用方法,Marker结合InfoWindow可展示更详尽的信息。本文将介绍以下内容:
- 构造
InfoWindow对象的两种方式; - 地图类显示和隐藏
InfoWindow的方法; - 自定义
InfoWindowAdapter类,通过Marker显示InfoWindow。
InfoWindow 相关类和接口
BaiduMap类
| 类型 | 方法 | 说明 |
|---|---|---|
| List< InfoWindow > |
getAllInfoWindows() |
5.4.0版本新增接口 获取已添加的所有InfoWindow对象 |
| void |
showInfoWindow(InfoWindow infoWindow) |
显示 InfoWindow,。 该接口会先隐藏其他已添加的InfoWindow, 再添加新的InfoWindow |
| void |
showInfoWindow(InfoWindow infoWindow, boolean isHideOthers) |
5.4.0版本新增接口 显示 InfoWindow。 该接口可以设置是否在添加InfoWindow之前,先隐藏其他已经添加的InfoWindow. |
| void |
showInfoWindows(List< InfoWindow > infoWindowList) |
5.4.0版本新增接口 添加多个InfoWindow |
| void |
hideInfoWindow() |
隐藏地图上的所有InfoWindow |
| void |
hideInfoWindow(InfoWindow infoWindow) |
5.4.0版本新增接口 清除特定的InfoWindow |
| void |
clear() |
清空地图所有的 Overlay 覆盖物以及 InfoWindow |
InfoWindow 类
构造方法
在地图中显示一个信息窗口,可以设置一个View作为该窗口的内容,也可以设置一个 BitmapDescriptor 作为该窗口的内容。
方式一:通过添加View在地图上展示,交互操作通过View实现。
方式二:将View转化为Bitmap渲染在地图上,交互操作通过InfoWindow实现。这种方法性能比第一种方法要高。
| 方法 | 说明 |
|---|---|
InfoWindow(BitmapDescriptor bd, LatLng position, int yOffset, InfoWindow.OnInfoWindowClickListener listener) |
通过传入的 BitmapDescriptor 构造一个 InfoWindow。 参数: bd - InfoWindow 展示的bitmap position - InfoWindow 显示的地理位置 yOffset - InfoWindow Y 轴偏移量 listener - InfoWindow 点击监听者 |
InfoWindow(View view, LatLng position, int yOffset) |
通过传入的 view 构造一个 InfoWindow, 此时只是利用该view生成一个Bitmap绘制在地图中,监听事件由开发者实现。 参数: view - InfoWindow 展示的 view position - InfoWindow 显示的地理位置 yOffset - InfoWindow Y 轴偏移量 |
InfoWindow(View view, LatLng position, int yOffset, boolean isFitDensityDpi, int targetDensityDpi) |
根据指定的像素密度对传入的view构造InfoWindow, 此时只是利用该view生成一个Bitmap绘制在地图中,监听事件由开发者实现。 参数: view - InfoWindow 展示的 view position - InfoWindow 显示的地理位置 yOffset - InfoWindow Y 轴偏移量 isFitDensityDpi - 是否适配设备像素密度,默认不适配 targetDensityDpi - 目标像素密度, 建议传入设备默认像素密度值,否则可能会展示效果无法到达预期 |
getter
| 类型 | 方法 | 说明 |
|---|---|---|
| BitmapDescriptor |
getBitmapDescriptor() |
获取InfoWindow的BitmapDescriptor资源 |
| LatLng |
getPosition() |
获取位置数据 |
| String |
getTag() |
获取InfoWindow的Tag |
| View |
getView() |
获取InfoWindow的View |
| int |
getYOffset() |
获取InfoWindow的YOffset偏移 |
setter
| 类型 | 方法 | 说明 |
|---|---|---|
| void |
setBitmapDescriptor(BitmapDescriptor mBitmapDescriptor) |
更新InfoWindow的BitmapDescriptor属性。 |
| void |
setPosition(LatLng mPosition) |
设置位置数据 |
| void |
setTag(String tag) |
设置InfoWindow的Tag |
| void |
setView(View mView) |
更新InfoWindow的View属性 注: 仅支持通过InfoWindow(View, LatLng, int, boolean, int) or InfoWindow(View, LatLng, int)两种方式创建 InfoWindow的更新; 如果是使用了InfoWindow(BitmapDescriptor, LatLng, int, OnInfoWindowClickListener)方式创建的 InfoWindow,则不要使用该接口更新View属性,否则可能出现View与BitmapDescriptor层叠的现象。 |
| void |
setYOffset(int mYOffset) |
设置InfoWindow的YOffset偏移 |
OnInfoWindowClickListener 接口
// 信息窗口点击事件监听接口
public interface OnInfoWindowClickListener {
// 信息窗口点击事件处理函数
void onInfoWindowClick();
}
InfoWindowAdapter 相关类和方法
自定义适配器InfoWindowAdapter并设置map.setInfoWindowAdapter(adapter),调用marker.showInfoWindow()即可实现显示InfoWindow。
BaiduMap类
| 类型 | 方法 | 说明 |
|---|---|---|
| void |
setInfoWindowAdapter(InfoWindowAdapter adapter) |
设置InfoWindowAdapter |
InfoWindowAdapter 接口
public interface InfoWindowAdapter {
View getInfoWindowView(Marker marker);
int getInfoWindowViewYOffset();
InfoWindow getInfoWindow(Marker marker);
}
Marker 类
Marker中的InfoWindow方法
| 类型 | 方法 | 说明 |
|---|---|---|
| void |
showInfoWindow() |
添加 Marker 关联的InfoWindow,两者的更新是相互独立的。 |
| 类型 | 方法 | 说明 |
|---|---|---|
| boolean | isInfoWindowEnabled() | 判断是否显示InfoWindow |
| InfoWindow | getInfoWindow() | 获取 Marker 绑定的InfoWindow |
| void | setPositionWithInfoWindow(LatLng position) | 设置 Marker 覆盖物的位置坐标,并同步更新与Marker关联的InfoWindow的位置坐标. |
| void | showInfoWindow(InfoWindow mInfoWindow) | 添加 Marker 关联的InfoWindow,两者的更新是相互独立的。 |
| void | showSmoothMoveInfoWindow(InfoWindow mInfoWindow) | 该接口适用于小车平滑移动中,InfoWindow需要跟随 Marker 频繁动态更新View属性的场景。 |
| void | hideInfoWindow() | 移除与 Marker 绑定的InfoWindow |
| void | updateInfoWindowBitmapDescriptor(BitmapDescriptor bitmapDescriptor) | 更新与Marker绑定的InfoWindow对应的BitmapDescriptor,适用于以BitmapDescriptor方式创建InfoWindow 注: 仅支持通过InfoWindow.InfoWindow(BitmapDescriptor, LatLng, int, InfoWindow.OnInfoWindowClickListener) 方式创建的InfoWindow的更新; |
| void | updateInfoWindowPosition(LatLng position) | 更新与Marker绑定的InfoWindow对应的位置 |
| void | updateInfoWindowView(View view) | 更新与Marker绑定的InfoWindow对应的View,适用于以View方式创建InfoWindow 注: 仅支持通过InfoWindow.InfoWindow(View, LatLng, int, boolean, int) or InfoWindow.InfoWindow(View, LatLng, int)两种方式创建的InfoWindow的更新; |
| void | updateInfoWindowYOffset(int yOffset) | 更新与Marker绑定的InfoWindow对应的yOffset |
示例
在地图上显示多个Marker覆盖物,点击Marker显示InfoWindow。其中InfoWindow显示的信息通过MarkerOptions的extraInfo传递。
界面布局

1-布局.png
- 布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.baidudemo.MapInfoWindowActivity">
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:clickable="true"
app:layout_constraintBottom_toTopOf="@id/bottomView"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottomView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/bmapView">
<RadioGroup
android:id="@+id/RadioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/background_dark"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:paddingHorizontal="10dp">
<RadioButton
android:id="@+id/viewMode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:onClick="setMarkerFlag"
android:text="View Mode"
android:textColor="@color/white"
android:textStyle="bold" />
<RadioButton
android:id="@+id/bitmapMode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="setMarkerFlag"
android:text="Bitmap Mode"
android:textColor="@color/white"
android:textStyle="bold" />
<RadioButton
android:id="@+id/adapter_mode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="setMarkerFlag"
android:text="Adapter Mode"
android:textColor="@color/white"
android:textStyle="bold" />
</RadioGroup>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
MapInfoWindow类
- 以下是
MapInfoWindow部分代码
常量
public static final String VIEW_MODE = "ViewMode";
public static final String BITMAP_MODE = "BitmapMode";
public static final String ADAPTER_MODE = "AdapterMode";
成员变量
// 覆盖物列表
List<Overlay> overlays = new ArrayList<>();
// 选中的状态
String selectedFlag = VIEW_MODE;
// 气泡图标
ArrayList<BitmapDescriptor> bitmaps = new ArrayList<>();
int yOffset = 0; // InfoWindow相对于point在y轴的偏移量
初始化
int[] drawableIds = BubbleIcons.Number;
for (int drawableId : drawableIds) {
BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(drawableId);
if (yOffset == 0)
yOffset = -bitmap.getBitmap().getHeight();
bitmaps.add(bitmap);
}
initEvent();
map.setInfoWindowAdapter(new MyInfoWindowAdapter());
- 点击
Marker显示InfoWindow。
private void initEvent() {
map.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
switch (selectedFlag) {
case VIEW_MODE:
showViewMode(marker);
break;
case BITMAP_MODE:
showBitmapMode(marker);
break;
case ADAPTER_MODE:
showAdapterMode(marker);
break;
}
return true;
}
});
}
创建与移除覆盖物
- 批量添加覆盖物,通过
MarkerOptions的extraInfo,向InfoWindow传递数据。
public void addMarkers() {
// 构造大量坐标数据
List<LatLng> points = new ArrayList<>();
points.add(new LatLng(39.97923, 116.357428));
points.add(new LatLng(39.94923, 116.397428));
points.add(new LatLng(39.97923, 116.437428));
points.add(new LatLng(39.92353, 116.490705));
points.add(new LatLng(40.023537, 116.289429));
points.add(new LatLng(40.022211, 116.406137));
// 创建OverlayOptions的集合
List<OverlayOptions> optionsList = new ArrayList<>();
for (int i = 0; i < points.size(); ++i) {
// 创建OverlayOptions属性
MarkerOptions option = new MarkerOptions()
.position(points.get(i))
.icon(bitmaps.get(i));
Bundle bundle = new Bundle();
bundle.putInt("id", i + 1);
option.extraInfo(bundle);
// 将OverlayOptions添加到list
optionsList.add(option);
}
// 在地图上批量添加
List<Overlay> newOverlays = map.addOverlays(optionsList);
overlays.addAll(newOverlays);
}
public void removeOverlay() {
// 批量删除添加的多个 Overlay
//map.removeOverLays(overlays);
// 清空地图所有的 Overlay 覆盖物以及 InfoWindow
// map.clear();
// 删除覆盖物
for (Overlay overlay : overlays) {
overlay.remove();
}
overlays.clear();
}
显示与隐藏InfowWindow
- 视图模式
// 使用View构造InfoWindow
private void showViewMode(Marker marker) {
LatLng latLng = marker.getPosition();
int id = marker.getExtraInfo().getInt("id");
// 用来构造InfoWindow的Button
Button button = new Button(context);
button.setBackgroundResource(R.drawable.popup);
button.setText("View示例-" + id);
button.setTextColor(Color.BLACK);
// 监听点击事件
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
map.hideInfoWindow();
}
});
// 创建InfoWindow
InfoWindow infoWindow = new InfoWindow(button, latLng, yOffset);
// 显示InfoWindow
map.showInfoWindow(infoWindow);
}
- 位图模式
private void showBitmapMode(Marker marker) {
LatLng latLng = marker.getPosition();
int id = marker.getExtraInfo().getInt("id");
Button button = new Button(context);
button.setBackgroundResource(R.drawable.popup);
button.setText("Bitmap示例-" + id);
button.setTextColor(Color.BLACK);
button.setWidth(400);
BitmapDescriptor bitmap = BitmapDescriptorFactory.fromView(button);
// InfoWindow点击事件监听接口
InfoWindow.OnInfoWindowClickListener listener;
// 监听点击事件
listener = new InfoWindow.OnInfoWindowClickListener() {
public void onInfoWindowClick() {
// 隐藏地图上的所有InfoWindow
map.hideInfoWindow();
}
};
// 创建InfoWindow
InfoWindow infoWindow = new InfoWindow(bitmap, latLng, yOffset, listener);
// 显示InfoWindow
map.showInfoWindow(infoWindow);
}
- 适配器模式
private void showAdapterMode(Marker marker) {
// 避免同时显示多个InfoWindow
map.hideInfoWindow();
marker.showInfoWindow();
}
- 自定义适配器
private class MyInfoWindowAdapter implements InfoWindowAdapter {
@Override
public View getInfoWindowView(Marker marker) {
return null;
}
@Override
public int getInfoWindowViewYOffset() {
return yOffset;
}
@Override
public InfoWindow getInfoWindow(Marker marker) {
LatLng latLng = marker.getPosition();
int id = marker.getExtraInfo().getInt("id");
Button button = new Button(context);
button.setBackgroundResource(R.drawable.popup);
button.setText("Adapter示例-" + id);
button.setTextColor(Color.BLACK);
button.setWidth(400);
BitmapDescriptor bitmap = BitmapDescriptorFactory.fromView(button);
// InfoWindow点击事件监听接口
InfoWindow.OnInfoWindowClickListener listener;
listener = new InfoWindow.OnInfoWindowClickListener() {
public void onInfoWindowClick() {
map.hideInfoWindow();
}
};
// 创建InfoWindow
return new InfoWindow(bitmap, latLng, yOffset, listener);
}
}
设置属性
public void setFlag(String flag) {
selectedFlag = flag;
// 隐藏地图上的所有InfoWindow
map.hideInfoWindow();
}
加载与移除地图
public void onMapLoaded() {
addMarkers();
setFlag(VIEW_MODE);
}
public void onMapDestroy() {
removeOverlay();
for (BitmapDescriptor bitmap : bitmaps) {
bitmap.recycle();
}
bitmaps = null;
}
MapInfoWindowActivity 类
- 以下是
MapInfoWindowActivity类部分代码
控件响应事件
public void setMarkerFlag(View view) {
boolean checked = ((RadioButton) view).isChecked();
if (!checked)
return;
int id = view.getId();
String flag;
if (id == R.id.viewMode)
flag = MapInfoWindow.VIEW_MODE;
else if (id == R.id.bitmapMode)
flag = MapInfoWindow.BITMAP_MODE;
else if (id == R.id.adapter_mode)
flag = MapInfoWindow.ADAPTER_MODE;
else
return;
mapInfoWindow.setFlag(flag);
}
运行效果图

2-效果图.png