高德地图SDK Android版开发 11 覆盖物示例 4 线
前言
文本通过创建多个不同线宽的折线和大地曲线,介绍Polyline的使用方法。
线的属性包括是否可点击、透明度、是否虚线、颜色和纹理属性、大地曲线。
- 颜色和纹理属性包括
分段颜色
、纹理
、分段纹理
、渐变色
。只能选一或不选。
为了直观显示线的属性,仅使用了CheckBox控件,多种属性只能选一通过代码实现。
界面布局
- 布局文件
<?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类部分代码。
常量
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"; // 大地曲线
- 渐变色
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, ……
final static int LINE_WIDTH_MIN = 5;
final static int LINE_GEODESIC_WIDTH_MIN = 15;
final static int LINE_WIDTH_STEP = 5;
成员变量
// 覆盖物列表
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<>(); // 渐变色
初始值
- 默认选中选项
selectedFlags.add(CLICKABLE);
- 多个折线
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)
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)
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();
private void initEvent() {
map.setOnPolylineClickListener(new AMap.OnPolylineClickListener() {
@Override
public void onPolylineClick(Polyline polyline) {
showToast("click polyline");
}
});
}
创建覆盖物
- 创建大地曲线或创建多个折线
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;
}
}
- 设置折线属性
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);
}
}
移除覆盖物
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();
}
设置属性
public void setFlags(List<String> flags) {
selectedFlags.clear();
selectedFlags.addAll(flags);
removeOverlay();
addOverlays();
}
加载地图和释放地图
public void onMapLoaded() {
addOverlays();
}
public void onMapDestroy() {
removeOverlay();
for (BitmapDescriptor bitmap : bitmaps) {
bitmap.recycle();
}
bitmaps = null;
}
MapPolylineActivity类
以下是MapPolylineActivity类部分代码
控件响应事件
说明:为了直观显示线的属性,仅使用了CheckBox控件,多种属性只能选一通过代码实现。
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();
}
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);
}