腾讯地图SDK Android版开发 10 InfoWindow

腾讯地图SDK Android版开发 10 InfoWindow

  • 前言
  • 介绍
    • 默认风格
    • 自定义样式
    • 实现方式
    • 交互操作
    • 播放信息窗口的动画
    • 开启多窗口模式
  • 相关类和接口
    • 默认样式
      • MarkerOptions 类
      • Marker 类
      • TencentMap类
      • TencentMap.OnInfoWindowClickListener 接口类
    • 自定义样式
      • TencentMap 类
      • TencentMap.InfoWindowAdapter 接口
  • 示例
    • 界面布局
    • MapInfoWindow类
      • 常量
      • 成员变量
      • 初始化
      • 创建与移除覆盖物
      • 设置属性
      • 自定义样式
      • 加载与移除地图
    • MapInfoWindowActivity 类
      • 控件响应事件
    • 运行效果图

前言

前文介绍的腾讯地图添加Marker覆盖物的使用方法,本文重点介绍如何结合Marker使用InfoWindow展示更多信息。

介绍

信息窗口,是依附于Marker之上的展现元素,用于对Marker进行详细描述。

腾讯地图SDK默认提供的InfoWindow分标题和简述两部分,开发者也可以自定义InfoWindow,满足个性化场景的要求。

主要功能有:

  1. 默认信息窗口的显示和隐藏

  2. 创建一个自定义信息窗口

  3. 注册信息窗口的事件监听

  4. 播放信息窗口的动画

  5. 开启多窗口模式

默认风格

  • 使用MarkerOptions或者Marker来开启InfoWindow和设置信息内容。

  • 当点击Marker的时候,将显示InfoWindow

  • 通过Marker的接口显示和隐藏InfoWindow

自定义样式

TencenMap接口中,TencentMap.InfoWindowAdapter类用来提供自定义窗口能力。

该类提供两个接口:无边框自定义View和带边框自定义View。

当配置了InfoWindowAdapter时,MarkerOptions中的titlesnippet属性即失效。

实现方式

InfoWindow有两种实现方式,开发者需要针对不同场景选择适合的类型,展示信息窗口。

  1. Bitmap型,通过View布局转化成Bitmap,然后由渲染引擎绘制在地图上展示。
  2. View型,通过View布局直接在地图上展示。

两者之间的对比表格:

类型 定制化 动画 性能 复杂度
Bitmap 有限
View 支持
  • 默认InfoWindow使用的是Bitmap类型,该类型整体是一张图片。

  • 还可以通过MarkerOptions指定当前MarkerInfoWindow使用View类型。

交互操作

  • SDK内置了InfoWindow的点击事件。

  • 通过TencentMap.setOnInfoWindowClickListener设置Marker气泡点击事件监听。

  • 当使用View类型时,infoWindow的事件监听由View来接管处理。也就是可以给View的任何一个子控件设置点击事件。

播放信息窗口的动画

  • 当使用Bitmap类型时,InfoWindow的动画由引擎内部支持,仅支持有限的几种动画类型,比如:渐变、缩放、平移、旋转。
  • 当使用View类型时,InfoWindow的动画由View系统支持,可由开发者自定义处理。

开启多窗口模式

  • 默认情况下,多窗口模式是关闭的,不能在地图上显示多个信息窗口。
  • 通过TencentMap.enableMultipleInfowindow(boolean)接口来开启和关闭多窗口模式。
  • 开启多窗口模式之后,在多个Marker上点击,都能正常显示信息窗口。

相关类和接口

默认样式

MarkerOptions 类

  • getter
类型 方法 说明
boolean isInfoWindowEnable() 获取标注的InfoWindow是否可以弹出气泡
boolean isViewInfowindow() 获取此 marker 的 infowindow 是否用 view 实现 infowindow
String getSnippet() 获取标注的InfoWindow(气泡)的内容
String getTitle() 获得标注的InfoWindow(气泡)的标题
  • setter
类型 方法 说明
MarkerOptions infoWindowEnable(boolean enabled) 设置标注是否可以弹出InfoWindow(气泡)
MarkerOptions viewInfoWindow(boolean enabled) 设置此 marker 的 infowindow 是否用 view 实现 infowindow
MarkerOptions title(String s) 设置标注的InfoWindow(气泡)的标题,如果设置了 TencentMap.setInfoWindowAdapter(TencentMap.InfoWindowAdapter) 则失效
MarkerOptions snippet(String snippet) 设置标注的InfoWindow(气泡)的内容,如果设置了 TencentMap.setInfoWindowAdapter(TencentMap.InfoWindowAdapter) 则失效
MarkerOptions infoWindowAnchor(float u, float v) 设置infowindow anchor point
MarkerOptions infoWindowOffset(int offsetX, int offsetY) 设置InfoWindow的偏移,在基准(InfoWindow在Marker正上方中间处显示 —— 默认位置)上偏移 方向:向右,向下为正方向,向左,向上为负方向
MarkerOptions infoWindowCollisionBy(MarkerCollisionItem… infoWindowCollisions) 设置InfoWindow 可被碰撞的类型,默认无碰撞关系

Marker 类

  • getter
类型 方法 说明
boolean isInfoWindowEnable() 获取标注的InfoWindow是否可以弹出气泡
String getSnippet() 获取标注的InfoWindow(气泡)的内容
String getTitle() 获得标注的InfoWindow(气泡)的标题
  • setter
类型 方法 说明
void setSnippet(String snippet) 设置标注的InfoWindow(气泡)的内容,如果设置了 TencentMap.setInfoWindowAdapter(TencentMap.InfoWindowAdapter) 则失效
void setTitle(String s) 设置标注的InfoWindow(气泡)的标题,如果设置了 TencentMap.setInfoWindowAdapter(TencentMap.InfoWindowAdapter) 则失效
void setInfoWindowEnable(boolean enabled) 设置标注是否可以弹出InfoWindow(气泡)
void setInfoWindowAnchor(float anchorU, float anchorV) 设置 infowindow 的锚点,默认 (0.5f, 1)
void setInfoWindowOffset(int offsetX, int offsetY) 设置 infowindow 坐标偏移
  • 显示,隐藏和更新InfoWindow
类型 方法 说明
boolean isInfoWindowShown() 获取让标注InfoWindow(气泡)是否正在显示
void showInfoWindow() 让标注显示InfoWindow(气泡)
void hideInfoWindow() 让标注隐藏InfoWindow(气泡)
void refreshInfoWindow() 更新infowindow

TencentMap类

类型 方法 说明
void enableMultipleInfowindow(boolean enable) 设置地图是否允许多InfoWindow模式,默认是false(只允许显示一个InfoWindow) 注意:此方法需要在addMarker之前调用。
void setOnTapMapViewInfoWindowHidden(boolean enable) 点击地图其他区域时,InfoWindow是否需要隐藏
void setOnInfoWindowClickListener(TencentMap.OnInfoWindowClickListener listener) 设置Marker气泡点击事件监听接口

TencentMap.OnInfoWindowClickListener 接口类

/**
 * 当 Marker 气泡窗口被点击时的回调
 */
public interface OnInfoWindowClickListener {
    /**
     * InfoWindow被点击时回调函数
     * @param Marker 被点击的InfoWindow所属的 Marker
     */
    void onInfoWindowClick(Marker Marker);

    /**
     * 当InfoWindow点击时,点击点的回调
     * @param windowWidth InfoWindow的宽度
     * @param windowHigh InfoWindow的高度
     * @param x 点击点在InfoWindow的x坐标点
     * @param y 点击点在InfoWindow的y坐标点
     */
    void onInfoWindowClickLocation(int windowWidth, int windowHigh, int x, int y);
}

自定义样式

TencentMap 类

类型 方法 说明
void setInfoWindowAdapter(TencentMap.InfoWindowAdapter infoWindowAdapter) 设置气泡样式接口

TencentMap.InfoWindowAdapter 接口

类型 方法 说明
View getInfoContents(Marker marker) 自定义气泡的标题和内容
View getInfoWindow(Marker marker) 自定义整个气泡的InfoWindow
/**
 * 自定义 Marker气泡样式接口
 */
public interface InfoWindowAdapter {
    /**
     * 自定义整个气泡的InfoWindow
     * @param Marker 当前要弹出InfoWindow的 Marker
     *               每个 marker 应返回自己的 view,不同 marker 在使用相同的 view 时会报错
     * @return View
     */
    View getInfoWindow(Marker Marker);

    /**
     * 自定义气泡的标题和内容
     * @param Marker 当前要弹出InfoWindow的 Marker
     *               每个 marker 应返回自己的 view,不同 marker 在使用相同的 view 时会报错
     * @return View
     */
    View getInfoContents(Marker Marker);
}

示例

界面布局

腾讯地图SDK Android版开发 10 InfoWindow_第1张图片

  • 布局文件

<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="MapInfoWindowActivity">

    <com.tencent.tencentmap.mapsdk.maps.TextureMapView
        android:id="@+id/mapview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        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/mapview">

        <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/simple_mode"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:checked="true"
                android:onClick="setMarkerFlag"
                android:text="简单"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <RadioButton
                android:id="@+id/adapter_window_mode"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1.5"
                android:onClick="setMarkerFlag"
                android:text="适配器(窗口)"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <RadioButton
                android:id="@+id/adapter_content_mode"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1.5"
                android:onClick="setMarkerFlag"
                android:text="适配器(内容)"
                android:textColor="@color/white"
                android:textStyle="bold" />
        RadioGroup>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center"
            android:background="@android:color/background_dark"
            android:orientation="horizontal"
            android:paddingHorizontal="10dp">

            <CheckBox
                android:id="@+id/multiple_info_window"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="setMultipleInfoWindow"
                android:text="多窗口"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <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/viewType"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:checked="false"
                    android:onClick="setInfoWindowType"
                    android:text="View类型"
                    android:textColor="@color/white"
                    android:textStyle="bold" />

                <RadioButton
                    android:id="@+id/bitmapType"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:checked="true"
                    android:onClick="setInfoWindowType"
                    android:text="Bitmap类型"
                    android:textColor="@color/white"
                    android:textStyle="bold" />

            RadioGroup>
        LinearLayout>
    androidx.appcompat.widget.LinearLayoutCompat>
androidx.constraintlayout.widget.ConstraintLayout>

MapInfoWindow类

  • 以下是MapInfoWIndows部分代码

常量

public static final String SIMPlE_MODE = "Simple";
public static final String ADAPTER_WINDOW_MODE = "AdapterWindowMode";
public static final String ADAPTER_CONTENT_MODE = "AdapterContentMode";

public static final String VIEW_TYPE = "ViewType";
public static final String BITMAP_TYPE = "BitmapType";

成员变量

// 覆盖物列表
List<Removable> overlays = new ArrayList<>();

// 选中的状态
String selectedMode = SIMPlE_MODE;
String selectedType = BITMAP_TYPE;

初始化

initEvent();
// 点击地图其他区域时,InfoWindow是否需要隐藏
map.setOnTapMapViewInfoWindowHidden(true);
private void initEvent() {
    map.setOnInfoWindowClickListener(new TencentMap.OnInfoWindowClickListener() {
        @Override
        public void onInfoWindowClick(Marker marker) {
            showToast("单击InfoWindow");
            // InfoWindow被点击时回调函数
            // marker.hideInfoWindow();
        }

        @Override
        public void onInfoWindowClickLocation(int windowWidth, int windowHigh, int x, int y) {
            // 当InfoWindow点击时,点击点的回调
        }
    });
}

创建与移除覆盖物

  • 创建覆盖物是设置InfoWindow是否用View实现
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));

    // 设置此marker的InfoWindow是否用View实现
    boolean isView = VIEW_TYPE.equals(selectedType);

    int[] icons = BubbleIcons.Number;
    for (int i = 0; i < points.size(); ++i) {
        // 构建Marker图标
        BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(icons[i]);
        // 构建MarkerOption,用于在地图上添加Marker
        MarkerOptions option = new MarkerOptions(points.get(i))
                .icon(bitmap)
                .title("标题" + (i + 1))
                .snippet("详细信息" + (i + 1))
                .viewInfoWindow(isView);

        // 在地图上添加Marker,并显示
        Marker marker = map.addMarker(option);
        overlays.add(marker);
    }
}

public void removeOverlay() {
    // 清除地图上所有的标注类(Marker、Polyline、Polygon,TileOverlay除外)
    // map.clearAllOverlays();

    // 从地图移除覆盖物
    for (Removable overlay : overlays) {
        if (overlay instanceof Marker) {
            Marker marker = (Marker) overlay;
            marker.hideInfoWindow();
        }
        if (!overlay.isRemoved())
            overlay.remove();
    }
    overlays.clear();
}

设置属性

public void enableMultipleInfoWindow(boolean enable) {
    // 设置地图是否允许多InfoWindow模式
    map.enableMultipleInfowindow(enable);
}

public void setSelectedMode(String flag) {
    selectedMode = flag;

    for (Removable overlay : overlays) {
        if (overlay instanceof Marker) {
            Marker marker = (Marker) overlay;
            // 让标注隐藏InfoWindow(气泡)
            marker.hideInfoWindow();
        }
    }

    switch (selectedMode) {
    case SIMPlE_MODE:
        map.setInfoWindowAdapter(null);
        break;
    case ADAPTER_WINDOW_MODE:
        map.setInfoWindowAdapter(new WindowModeAdapter());
        break;
    case ADAPTER_CONTENT_MODE:
        map.setInfoWindowAdapter(new ContentModeAdapter());
        break;
    }
}

public void setSelectedType(String flag) {
    selectedType = flag;

    removeOverlay();
    addMarkers();
}

自定义样式

  • 自定义布局custom_infowindow.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorLightBlue"> 

    
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:gravity="start|center"
        android:textColor="@color/black"
        android:textSize="18sp" />

LinearLayout>
  • WindowModeAdapterContentModeAdapter
private class WindowModeAdapter implements TencentMap.InfoWindowAdapter {
    @Override
    public View getInfoWindow(Marker marker) {
        return createCustomInfoView(marker);
    }

    @Override
    public View getInfoContents(Marker marker) {
        return null;
    }
}

private class ContentModeAdapter implements TencentMap.InfoWindowAdapter {
    @Override
    public View getInfoWindow(Marker marker) {
        return null;
    }

    @Override
    public View getInfoContents(Marker marker) {
        return createCustomInfoView(marker);
    }
}

private View createCustomInfoView(Marker marker) {
    View view = LayoutInflater.from(context).inflate(R.layout.custom_infowindow, null);
    TextView tvTitle = view.findViewById(R.id.tv_title);
    // 设置自定义信息窗的内容
    tvTitle.append(marker.getTitle() + "\n" + marker.getSnippet());
    return view;
}

加载与移除地图

public void onMapLoaded() {
    addMarkers();
}

public void onMapDestroy() {
    removeOverlay();
}

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.simple_mode)
        flag = mapInfoWindow.SIMPlE_MODE;
    else if (id == R.id.adapter_window_mode)
        flag = mapInfoWindow.ADAPTER_WINDOW_MODE;
    else if (id == R.id.adapter_content_mode)
        flag = mapInfoWindow.ADAPTER_CONTENT_MODE;
    else
        return;

    mapInfoWindow.setSelectedMode(flag);
}
  • 设置多窗口
public void setMultipleInfoWindow(View view) {
    boolean checked = ((CheckBox) view).isChecked();

    int id = view.getId();
    if (id == R.id.multiple_info_window) {
        mapInfoWindow.enableMultipleInfoWindow(checked);
    }
}
  • 设置InfoWindow显示方式:View或Bitmap
public void setInfoWindowType(View view) {
    boolean checked = ((RadioButton) view).isChecked();
    if (!checked)
        return;

    int id = view.getId();
    String flag;
    if (id == R.id.viewType)
        flag = mapInfoWindow.VIEW_TYPE;
    else if (id == R.id.bitmapType)
        flag = mapInfoWindow.BITMAP_TYPE;
    else
        return;

    mapInfoWindow.setSelectedType(flag);
}

运行效果图

简单 适配器(窗口) 适配器(内容)
自定义整个气泡的InfoWindow 自定义气泡的标题和内容

你可能感兴趣的:(腾讯地图Android开发,android,腾讯地图)