百度地图SDK Android版开发 10 InfoWindow

前言

前文介绍百度地图添加Marker的使用方法,Marker结合InfoWindow可展示更详尽的信息。本文将介绍以下内容:

  1. 构造InfoWindow对象的两种方式;
  2. 地图类显示和隐藏InfoWindow的方法;
  3. 自定义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显示的信息通过MarkerOptionsextraInfo传递。

界面布局

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;
        }
    });
}

创建与移除覆盖物

  • 批量添加覆盖物,通过MarkerOptionsextraInfo,向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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容