实现如下图一样的小工具
操作说明:
1.在地图上长按选点,第一个点添加起点marker,底部导航点为红色表示正在编辑
2.连续选点会弹出气泡计算总距离,底部导航点为红色表示正在编辑
3.点击气泡内垃圾桶会删除当前点,回退到上次内容.
4.点击红色按钮会清除已所有绘制内容
下面开始准备工作:
一、配置工作
1.app moudle的build.gradle文件内引入Amap依赖
//3D地图so及jar
implementation 'com.amap.api:3dmap:6.8.0'
2.AndroidManifest添加使用到的权限
<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 允许程序获取网络状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 允许程序访问WiFi网络信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 允许改变wifi连接状态 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- 写入权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--读取权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
AndroidManifest的application节点下配置AMap的key
<!-- 配置AMap 的key -->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="@string/map_key" />
3.string.xml内容
<resources>
<string name="app_name">Measure</string>
<string name="map_key">your key</string>
</resources>
二、开始编码工作
1.编写activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--引入MapView-->
<com.amap.api.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!--添加清除按钮-->
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="13dp"
android:layout_marginBottom="100dp"
android:clickable="true"
android:focusable="true"
android:src="@drawable/clear_map"
app:backgroundTint="#FFFF0000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</android.support.constraint.ConstraintLayout>
2.custom_info_window.xml 这个是自定义Marker的infowidow的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="40dp">
<TextView
android:id="@+id/info_distance"
android:layout_weight="1"
android:gravity="center"
android:text="距离:xxxm"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="#FF000000"
android:layout_width="1dp"
android:layout_height="30dp" />
<ImageView
android:id="@+id/info_delete"
android:src="@drawable/ic_remove_circle"
android:padding="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
3.java代码 核心绘制工具类
MeasureHelper.java
package com.ming.measure;
import android.content.Context;
import android.widget.Toast;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.Polyline;
import com.amap.api.maps.model.PolylineOptions;
import java.util.ArrayList;
import java.util.List;
public class MeasureHelper {
//起点marker
private Marker drawStartMarker = null;
//记录最后一个marker
private Marker lastClickMarker = null;
//所有点的集合
private List<LatLng> lineLatLngList = new ArrayList<>();
//线
private Polyline polyline = null;
//地图对象
private AMap mMap;
private Context ctx;
public MeasureHelper(Context context, AMap aMap) {
this.mMap = aMap;
this.ctx = context;
}
/**
* 划marker与线
*/
public void drawMarkerLine(LatLng addLatLng) {
//1.绘制此次Marker
Marker addMarker = mMap.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(addLatLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.red_point)));
//2.判断划线
if (lastClickMarker != null) {
if (drawStartMarker == null) {
drawStartMarker = mMap.addMarker(new MarkerOptions().position(lastClickMarker.getPosition()).icon(BitmapDescriptorFactory.fromResource(R.drawable.start)));
}
//显示距离
addMarker.showInfoWindow();
//红点变蓝点
lastClickMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.blue_point));
}
//划线
drawLine(addLatLng);
//3.本次为最新Marker
lastClickMarker = addMarker;
}
/**
* 划线
*/
private void drawLine(LatLng addLatLng) {
lineLatLngList.add(addLatLng);
if (lineLatLngList.size() > 1) {
if (polyline == null) {
polyline = mMap.addPolyline(
new PolylineOptions()
.addAll(lineLatLngList)
.width(30)
.setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.grasp_trace_line)));
} else {
polyline.setPoints(lineLatLngList);
}
} else {
Toast.makeText(ctx, "Go On!!!", Toast.LENGTH_SHORT).show();
}
}
public void clearMap() {
lineLatLngList.clear();
lastClickMarker = null;
drawStartMarker = null;
polyline = null;
if (mMap != null) {
mMap.clear();
Toast.makeText(ctx, "Cleared!!!", Toast.LENGTH_SHORT).show();
}
}
/**
* 获取距离
*
* @return
*/
public int getDistance() {
int distance = 0;
if (lineLatLngList != null) {
int listSize = lineLatLngList.size();
if (listSize > 1) {
LatLng lastLatLng = lineLatLngList.get(0);
for (int i = 1; i < listSize; i++) {
LatLng indexLatLng = lineLatLngList.get(i);
distance = (int) (distance + AMapUtils.calculateLineDistance(lastLatLng, indexLatLng));
lastLatLng = indexLatLng;
}
}
}
return distance;
}
/**
* 回退删除一步
*
* @param marker
*/
public void removeCurrent(Marker marker) {
try {
//移除点
int deleteIndex = lineLatLngList.size() - 1;
lineLatLngList.remove(deleteIndex);
//更新图形
polyline.setPoints(lineLatLngList);
//移除这个Marker
marker.remove();
//找到上一个点,改为红色,赋值lastMarker,显示InfoWindow(注:只剩一个点删除掉起点)
LatLng lastLatLng = lineLatLngList.get(deleteIndex - 1);
if (deleteIndex == 1) {
//起点删除
drawStartMarker.remove();
drawStartMarker = null;
//赋值
Marker findedMarker = findMarker(lastLatLng);
if (findedMarker != null) {
//蓝变红
findedMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.red_point));
//赋值上一个
lastClickMarker = findedMarker;
}
} else {
//赋值
Marker findedMarker = findMarker(lastLatLng);
if (findedMarker != null) {
// 显示气泡
findedMarker.showInfoWindow();
//蓝变红
findedMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.red_point));
//赋值上一个
lastClickMarker = findedMarker;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private Marker findMarker(LatLng position) {
List<Marker> markerList = mMap.getMapScreenMarkers();
for (Marker mk : markerList) {
if (mk.getPosition().equals(position)) {
return mk;
}
}
return null;
}
}
4.MainActivity.java 具体实现的代码
package com.ming.measure;
import android.content.Intent;
import android.os.PersistableBundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.amap.api.maps.AMap;
import com.amap.api.maps.MapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
public class MainActivity extends AppCompatActivity implements CheckPermissionUtil.PermissionCallBack, AMap.InfoWindowAdapter, AMap.OnMapLoadedListener, AMap.OnMapLongClickListener, AMap.OnMarkerClickListener {
//地图ui
private MapView mapView;
private AMap aMap;
private MeasureHelper drawLineHelper;
//按钮
private FloatingActionButton fab_clear;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//地图
mapView = findViewById(R.id.map);
mapView.onCreate(savedInstanceState);
aMap = mapView.getMap();
//按钮
fab_clear = findViewById(R.id.fab_clear);
initUiSettings();
initMapListener();
fab_clear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (drawLineHelper != null) {
drawLineHelper.clearMap();
}
}
});
}
//region 地图初始化参数
private void initUiSettings() {
//显示地图文字
aMap.showMapText(true);
UiSettings uiSettings = aMap.getUiSettings();
uiSettings.setMyLocationButtonEnabled(false);
//显示指南针
uiSettings.setCompassEnabled(true);
//显示缩放比例尺
uiSettings.setScaleControlsEnabled(true);
}
private void initMapListener() {
aMap.setInfoWindowAdapter(this);
aMap.setOnMapLoadedListener(this);
aMap.setOnMapLongClickListener(this);
aMap.setOnMarkerClickListener(this);
}
//endregion
//region 生命周期
@Override
protected void onResume() {
super.onResume();
if (mapView != null) {
mapView.onResume();
}
}
@Override
protected void onPause() {
super.onPause();
if (mapView != null) {
mapView.onPause();
}
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
if (mapView != null) {
mapView.onSaveInstanceState(outState);
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
if (mapView != null) {
mapView.onLowMemory();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mapView != null) {
mapView.onDestroy();
}
}
//endregion
//region 权限处理
private void checkAllPermission() {
if (getCheckPermissionUtil().checkWriteExternalStorage(MainActivity.this)) {
if (getCheckPermissionUtil().checkReadExternalStorage(MainActivity.this)) {
}
}
}
private CheckPermissionUtil checkPermissionUtil = null;
private CheckPermissionUtil getCheckPermissionUtil() {
if (null == checkPermissionUtil) {
checkPermissionUtil = new CheckPermissionUtil(this);
}
return checkPermissionUtil;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
checkAllPermission();
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
getCheckPermissionUtil().onRequestPermissionsResult(MainActivity.this, requestCode, permissions, grantResults);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void onAllow(int permissionCode) {
checkAllPermission();
}
@Override
public void onDeny(int permissionCode) {
checkAllPermission();
}
//endregion
//region 地图监听
/**
* 自定义InfoWindow实现的方法1
*/
@Override
public View getInfoWindow(final Marker marker) {
View view = View.inflate(this, R.layout.custom_info_window, null);
TextView info_tv_distance = view.findViewById(R.id.info_distance);
String distanceDes = "";
if (drawLineHelper != null) {
int distance = drawLineHelper.getDistance();
distanceDes = "距离:" + distance + "m";
}
info_tv_distance.setText(distanceDes);
ImageView info_iv_delete = view.findViewById(R.id.info_delete);
info_iv_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (drawLineHelper != null) {
drawLineHelper.removeCurrent(marker);
}
}
});
return view;
}
/**
* 自定义InfoWindow实现的方法2
*/
@Override
public View getInfoContents(Marker marker) {
return null;
}
/**
*amap 加载完成回调
*/
@Override
public void onMapLoaded() {
drawLineHelper = new MeasureHelper(MainActivity.this.getApplicationContext(), aMap);
checkAllPermission();
}
/**
*marker长按监听
*/
@Override
public void onMapLongClick(LatLng latLng) {
if (drawLineHelper != null) {
drawLineHelper.drawMarkerLine(latLng);
}
}
/**
*marker点击监听
*/
@Override
public boolean onMarkerClick(Marker marker) {
marker.showInfoWindow();
return true;
}
//endregion
}
核心内容都已经贴出来了,也可以去我的资源里下载源码,运行起来体验一下