高德地图SDK Android版开发 11 覆盖物示例 4 线

高德地图SDK Android版开发 11 覆盖物示例 4 线

前言

文本通过创建多个不同线宽的折线和大地曲线,介绍Polyline的使用方法。

线的属性包括是否可点击、透明度、是否虚线、颜色和纹理属性、大地曲线。

  • 颜色和纹理属性 包括分段颜色纹理分段纹理渐变色。只能选一或不选。

为了直观显示线的属性,仅使用了CheckBox控件,多种属性只能选一通过代码实现。

界面布局

  • 布局文件
xml 复制代码
<?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=".MapPolylineActivity">

    <com.amap.api.maps.MapView
        android:id="@+id/map"
        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/map">

        <LinearLayout
            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">

            <CheckBox
                android:id="@+id/clickable"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:checked="true"
                android:enabled="false"
                android:onClick="setMarkerFlag"
                android:text="点击"
                android:textColor="@android:color/darker_gray"
                android:textStyle="bold" />

            <CheckBox
                android:id="@+id/transparency"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="透明度"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <CheckBox
                android:id="@+id/dottedLine"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="虚线"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <CheckBox
                android:id="@+id/colors"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="分段颜色"
                android:textColor="@color/yellow_800"
                android:textStyle="bold" />

        </LinearLayout>

        <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/texture"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="纹理"
                android:textColor="@color/yellow_800"
                android:textStyle="bold" />

            <CheckBox
                android:id="@+id/textures"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="分段纹理"
                android:textColor="@color/yellow_800"
                android:textStyle="bold" />

            <CheckBox
                android:id="@+id/gradient"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:checked="false"
                android:onClick="setMarkerFlag"
                android:text="渐变色"
                android:textColor="@color/yellow_800"
                android:textStyle="bold" />

            <CheckBox
                android:id="@+id/geodesic"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="大地曲线"
                android:textColor="@color/white"
                android:textStyle="bold" />

        </LinearLayout>
    </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

MapPolyline类

以下为MapPolyline类部分代码。

常量

java 复制代码
public static final String CLICKABLE = "clickable"; // 点击
public static final String TRANSPARENCY = "transparency"; // 透明度
public static final String DOTTED_LINE = "DottedLine"; // 虚线
public static final String COLORS = "Colors"; // 分段颜色
public static final String TEXTURE = "Texture"; // 纹理
public static final String TEXTURES = "Textures"; // 分段纹理
public static final String GRADIENT = "Gradient"; // 渐变色
public static final String GEODESIC = "Geodesic"; // 大地曲线
  • 渐变色
java 复制代码
final static int COLOR_RED = 0xAAD50000;
final static int COLOR_YELLOW = 0xAAF57F17;
final static int COLOR_BLUE = 0xAA0D47A1;
final static int COLOR_GREEN = 0xAA33691E;
  • 折线线宽:
    • 多个折线的宽度依次为5,10, 15, ......
    • 多个大地曲线的宽度依次为15,20,25, ......
java 复制代码
final static int LINE_WIDTH_MIN = 5;
final static int LINE_GEODESIC_WIDTH_MIN = 15;
final static int LINE_WIDTH_STEP = 5;

成员变量

java 复制代码
// 覆盖物列表
List<BaseOverlay> overlays = new ArrayList<>();
// 选中的状态
List<String> selectedFlags = new ArrayList<>();

List<List<LatLng>> lines = new ArrayList<>(); // 多个折线
List<List<LatLng>> geodesicLines = new ArrayList<>(); // 大地曲线坐标 仅两个点
ArrayList<BitmapDescriptor> bitmaps = new ArrayList<>(); // 纹理
List<Integer> colorValues = new ArrayList<>(); // 渐变色

初始值

  • 默认选中选项
java 复制代码
selectedFlags.add(CLICKABLE);
  • 多个折线
java 复制代码
double latSpan = 0.05;
for (int i = 0; i < 5; ++i) {
    List<LatLng> points = new ArrayList<>();
    points.add(new LatLng(39.865 + latSpan * i, 116.254));
    points.add(new LatLng(39.865 + latSpan * i, 116.304));
    points.add(new LatLng(39.825 + latSpan * i, 116.354));
    points.add(new LatLng(39.855 + latSpan * i, 116.394));
    points.add(new LatLng(39.805 + latSpan * i, 116.454));
    points.add(new LatLng(39.865 + latSpan * i, 116.504));
    points.add(new LatLng(39.805 + latSpan * i, 116.544));
    lines.add(points);
}
  • 多个大地曲线(跨越180°的线跨越-180°的线来自官方Demo)
java 复制代码
List<LatLng> geodesicLine1 = new ArrayList<>();
geodesicLine1.add(new LatLng(36.53, 360 - 121.47, false));
geodesicLine1.add(new LatLng(22.33, 114, false));
geodesicLines.add(geodesicLine1);

/**
 *  从左到右绘制一条跨越180°的线,右边部分需要处理成超过180度
 *  正常经纬度范围是(-180°,180°),
 *  这里为了可以超过180°第三个参数填写false,表示去除内部检查
 */
List<LatLng> geodesicLine2 = new ArrayList<>();
geodesicLine2.add(new LatLng(59.304104, 133.44508, false));
geodesicLine2.add(new LatLng(62.220912, 145.573986, false));
geodesicLine2.add(new LatLng(64.353281, 158.75758, false));
geodesicLine2.add(new LatLng(64.880724, 170.886486, false));
geodesicLine2.add(new LatLng(66.261601, 360 - 179.269764, false));
geodesicLine2.add(new LatLng(66.048417, 360 - 155.539295, false));
geodesicLine2.add(new LatLng(65.251242, 360 - 143.234608, false));
geodesicLines.add(geodesicLine2);

/**
 * 从右到左绘制一条跨越-180°的线,左边部分会超过-180°,效果和跨域180°一样
 * 也可以将点全部+360°转换成跨域180°的线
 */
List<LatLng> geodesicLine3 = new ArrayList<>();
geodesicLine3.add(new LatLng(65.251242 - 10, -143.234608, false));
geodesicLine3.add(new LatLng(66.048417 - 10, -155.539295, false));
geodesicLine3.add(new LatLng(66.261601 - 10, -179.269764, false));
geodesicLine3.add(new LatLng(64.880724 - 10, 170.886486 - 360, false));
geodesicLine3.add(new LatLng(64.353281 - 10, 158.75758 - 360, false));
geodesicLine3.add(new LatLng(62.220912 - 10, 145.573986 - 360, false));
geodesicLine3.add(new LatLng(59.304104 - 10, 133.44508 - 360, false));
geodesicLines.add(geodesicLine3);
  • 纹理和颜色(纹理图来自官方Demo)
java 复制代码
final int[] drawableIds = {
        R.drawable.map_alr,
        R.drawable.map_alr_night,
        R.drawable.custtexture,
};
for (int id : drawableIds) {
    bitmaps.add(BitmapDescriptorFactory.fromResource(id));
}

final int[] colors = {COLOR_RED, COLOR_YELLOW, COLOR_BLUE, COLOR_GREEN};
for (int color : colors)
    colorValues.add(color);
  • 点击事件

    initEvent();

java 复制代码
private void initEvent() {
    map.setOnPolylineClickListener(new AMap.OnPolylineClickListener() {
        @Override
        public void onPolylineClick(Polyline polyline) {
            showToast("click polyline");
        }
    });
}

创建覆盖物

  • 创建大地曲线或创建多个折线
java 复制代码
public void addOverlays() {
    boolean isGeodesic = selectedFlags.contains(GEODESIC);
    List<List<LatLng>> showLines = isGeodesic ? geodesicLines : lines;
    int width = isGeodesic ? LINE_GEODESIC_WIDTH_MIN : LINE_WIDTH_MIN;
    for (List<LatLng> points : showLines) {
        PolylineOptions polylineOptions = new PolylineOptions()
                // 设置线段的宽度,默认为10
                .width(width)
                // 设置线段的颜色,需要传入32位的ARGB格式
                .color(COLOR_RED)
                // 设置Polyline头尾形状类型
                .lineCapType(PolylineOptions.LineCapType.LineCapRound)
                // 设置Polyline拐点衔接的形状类型
                .lineJoinType(PolylineOptions.LineJoinType.LineJoinRound)
                // 追加一批顶点到线段的坐标集合
                .addAll(points);

        setOption(polylineOptions, selectedFlags);

        // 在地图上绘制折线
        Polyline polyline = map.addPolyline(polylineOptions);
        overlays.add(polyline);

        width += LINE_WIDTH_STEP;
    }
}
  • 设置折线属性
java 复制代码
private void setOption(PolylineOptions option, List<String> flags) {
    if (flags.contains(DOTTED_LINE)) {
        // 设置是否画虚线
        option.setDottedLine(true);
        // 设置虚线形状
        // PolylineOptions.DOTTEDLINE_TYPE_SQUARE = 0;
        // PolylineOptions.DOTTEDLINE_TYPE_CIRCLE = 1;
        option.setDottedLineType(PolylineOptions.DOTTEDLINE_TYPE_CIRCLE);
    }

    if (flags.contains(TRANSPARENCY)) {
        // 设置线段的透明度0~1,默认是1,1表示不透明
        float transparency = 0.5f;
        option.transparency(transparency);
    }

    if (flags.contains(COLORS)) {
        // 设置线段的颜色
        option.colorValues(colorValues);
    }

    if (flags.contains(TEXTURE)) {
        // 设置是否使用纹理贴图画线
        option.setUseTexture(true);
        // 设置线段的纹理图,图片为2的n次方
        option.setCustomTexture(bitmaps.get(0));
    }

    if (flags.contains(TEXTURES)) {
        // 添加纹理索引
        List<Integer> indexList = new ArrayList<>();
        for (int i = 0; i < bitmaps.size(); ++i)
            indexList.add(i);

        // 设置是否使用纹理贴图画线
        option.setUseTexture(true);
        // 设置线段纹理list
        option.setCustomTextureList(bitmaps);
        // 设置线段纹理index数组
        option.setCustomTextureIndex(indexList);
    }

    if (flags.contains(GRADIENT)) {
        // 设置线段是否使用渐变色
        option.useGradient(true);
        // 设置线段的颜色
        option.colorValues(colorValues);
    }

    if (flags.contains(GEODESIC)) {
        // 设置线段是否为大地曲线
        option.geodesic(true);
    }
}

移除覆盖物

java 复制代码
public void removeOverlay() {
    // 从地图上删除所有的覆盖物(marker,circle,polyline 等对象),
    // 但myLocationOverlay(内置定位覆盖物)除外。
//        boolean isKeepMyLocationOverlay = true;
//        map.clear(isKeepMyLocationOverlay);

    for (BaseOverlay overlay : overlays) {
        if (overlay instanceof Polyline) {
            Polyline polyline = (Polyline) overlay;
            polyline.remove();
        }
    }
    overlays.clear();
}

设置属性

java 复制代码
public void setFlags(List<String> flags) {
    selectedFlags.clear();
    selectedFlags.addAll(flags);

    removeOverlay();
    addOverlays();
}

加载地图和释放地图

java 复制代码
public void onMapLoaded() {
    addOverlays();
}

public void onMapDestroy() {
    removeOverlay();

    for (BitmapDescriptor bitmap : bitmaps) {
        bitmap.recycle();
    }
    bitmaps = null;
}

MapPolylineActivity类

以下是MapPolylineActivity类部分代码

控件响应事件

说明:为了直观显示线的属性,仅使用了CheckBox控件,多种属性只能选一通过代码实现。

java 复制代码
public void setMarkerFlag(View view) {
    // 分段颜色、纹理、分段纹理、渐变色
    List<Integer> group = Arrays.asList(
            R.id.colors, R.id.texture, R.id.textures, R.id.gradient);

    boolean checked = ((CheckBox) view).isChecked();
    int id = view.getId();
    if (checked) {
        if (group.contains(id)) {
            for (int checkBoxId : group) {
                if (checkBoxId != id) {
                    ((CheckBox) findViewById(checkBoxId)).setChecked(false);
                }
            }
        }
    }

    update();
}
java 复制代码
private void update() {
    final int[] ids = {
            R.id.clickable,
            R.id.transparency,
            R.id.dottedLine,
            R.id.colors,
            R.id.texture,
            R.id.textures,
            R.id.gradient,
            R.id.geodesic,
    };
    final String[] options = {
            MapPolyline.CLICKABLE,
            MapPolyline.TRANSPARENCY,
            MapPolyline.DOTTED_LINE,
            MapPolyline.COLORS,
            MapPolyline.TEXTURE,
            MapPolyline.TEXTURES,
            MapPolyline.GRADIENT,
            MapPolyline.GEODESIC,
    };
    List<String> flags = new ArrayList<>();
    for (int i = 0; i < ids.length; ++i) {
        CheckBox checkBox = findViewById(ids[i]);
        if (checkBox.isChecked())
            flags.add(options[i]);
    }
    mapPolyline.setFlags(flags);
}

运行效果图

相关推荐
拭心11 分钟前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王2 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡3 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道3 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库4 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道5 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe5 小时前
Android Hook - 动态加载so库
android
居居飒5 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He8 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗9 小时前
Android笔试面试题AI答之Android基础(1)
android