[Opt]高德的小地图封装到View中

This commit is contained in:
chenfufeng
2023-02-03 17:37:51 +08:00
parent 21d6c665f3
commit efe80d9ea8

View File

@@ -0,0 +1,350 @@
package com.mogo.eagle.core.function.smp.view
import android.content.Context
import android.graphics.Color
import android.os.Bundle
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.RelativeLayout
import androidx.annotation.UiThread
import com.amap.api.maps.*
import com.amap.api.maps.model.*
import com.mogo.cloud.commons.utils.CoordinateUtils
import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.map.MogoLatLng
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager.getGlobalPath
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ20ListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager
import com.mogo.eagle.core.function.map.R
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.MapAssetStyleUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import mogo.telematics.pad.MessagePad
import java.util.*
import kotlin.math.floor
class SmallMapView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr), IMoGoChassisLocationGCJ02Listener,
IMoGoPlanningRottingListener,
IMoGoAutopilotStatusListener {
private var mAMapNaviView: TextureMapView? = null
private var mAMap: AMap? = null
private var mCarMarker: Marker? = null
private var mStartMarker: Marker? = null
private var mEndMarker: Marker? = null
private val zoomLevel = 15
private val mCoordinatesLatLng: MutableList<LatLng> = ArrayList()
private var mPolyline: Polyline? = null
private var mCameraUpdate: CameraUpdate? = null
private var mContext: Context? = null
private var mLocation: MogoLocation? = null
private var autoPilotStatus = 0
companion object {
const val TAG = "SmallMapView"
}
init {
try {
initView(context)
} catch (e: Exception) {
e.printStackTrace()
}
}
// =================必须通知高德地图生命周期的变化=================
fun onCreateView(savedInstanceState: Bundle?) {
if (mAMapNaviView != null) {
mAMapNaviView!!.onCreate(savedInstanceState)
}
}
fun onResume() {
if (mAMapNaviView != null) {
mAMapNaviView!!.onResume()
}
}
fun onPause() {
if (mAMapNaviView != null) {
mAMapNaviView!!.onPause()
}
}
fun onDestroy() {
if (mAMapNaviView != null) {
mAMapNaviView!!.onDestroy()
}
}
// =================必须通知高德地图生命周期的变化=================
fun convert(coordinates: List<MogoLatLng>) {
mCoordinatesLatLng.clear()
val latLngs = coordinateConverterFrom84ForList(mContext, coordinates)
mCoordinatesLatLng.addAll(latLngs)
}
@UiThread
fun drawablePolyline() {
clearPolyline()
if (mAMap != null) {
if (mCoordinatesLatLng.size > 2) {
// 设置开始结束Marker位置
mStartMarker!!.position = mCoordinatesLatLng[0]
mEndMarker!!.position = mCoordinatesLatLng[mCoordinatesLatLng.size - 1]
mStartMarker!!.setToTop()
mStartMarker!!.isVisible = true
mEndMarker!!.isVisible = true
mEndMarker!!.setToTop()
//存放所有点的经纬度
val boundsBuilder = LatLngBounds.Builder()
for (i in mCoordinatesLatLng.indices) {
//把所有点都include进去LatLng类型
boundsBuilder.include(mCoordinatesLatLng[i])
}
//第二个参数为四周留空宽度
mAMap!!.animateCamera(
CameraUpdateFactory.newLatLngBounds(
boundsBuilder.build(),
30
)
)
// 绘制线
mPolyline = mAMap!!.addPolyline(
PolylineOptions()
.addAll(mCoordinatesLatLng)
.color(Color.argb(255, 31, 127, 255))
.width(12f)
)
}
}
}
@UiThread
fun clearPolyline() {
if (mPolyline != null) {
mPolyline!!.remove()
}
if (mStartMarker != null) {
mStartMarker!!.isVisible = false
}
if (mEndMarker != null) {
mEndMarker!!.isVisible = false
}
}
private fun initView(context: Context) {
mContext = context
val smpView = LayoutInflater.from(context).inflate(R.layout.module_small_map_view, this)
mAMapNaviView = smpView.findViewById(R.id.aMapNaviView)
initAMapView()
// 注册定位监听
CallerChassisLocationGCJ20ListenerManager.addListener(TAG, this)
CallerPlanningRottingListenerManager.addListener(TAG, this)
CallerAutoPilotStatusListenerManager.addListener(TAG, this)
startTask()
}
private fun initAMapView() {
mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel.toFloat())
mAMap = mAMapNaviView!!.map
// 关闭地图文字标注
mAMap?.showMapText(false)
// 设置导航地图模式aMap是地图控制器对象。
mAMap?.mapType = AMap.MAP_TYPE_NIGHT
// 关闭显示实时路况图层aMap是地图控制器对象。
mAMap?.isTrafficEnabled = false
// 设置 锚点 图标
mCarMarker = if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)) {
mAMap?.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.map_bus_icon))
.anchor(0.5f, 0.5f)
)
} else {
mAMap?.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.map_car_icon))
.anchor(0.5f, 0.5f)
)
}
mStartMarker = mAMap?.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_dir_start))
)
mEndMarker = mAMap?.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_dir_end))
)
// 加载自定义样式
val customMapStyleOptions = CustomMapStyleOptions()
.setEnable(true)
.setStyleData(MapAssetStyleUtils.getAssetsStyle(context, "over_view_style.data"))
.setStyleExtraData(
MapAssetStyleUtils.getAssetsExtraStyle(
context,
"over_view_style_extra.data"
)
)
// 设置自定义样式
mAMap?.setCustomMapStyle(customMapStyleOptions)
//设置希望展示的地图缩放级别
mAMap?.moveCamera(mCameraUpdate)
// 设置地图的样式
val uiSettings = mAMap?.uiSettings
uiSettings?.isZoomControlsEnabled = false // 地图缩放级别的交换按钮
uiSettings?.setAllGesturesEnabled(false) // 所有手势
uiSettings?.isMyLocationButtonEnabled = false // 显示默认的定位按钮
uiSettings?.setLogoBottomMargin(-150) //设置Logo下边界距离屏幕底部的边距,设置为负值即可
mAMap?.setOnMapLoadedListener(AMap.OnMapLoadedListener {
CallerLogger.d(
SceneConstant.M_MAP + TAG,
"smp---onMapLoaded"
)
// 加载自定义样式
val customMapStyleOptions1 = CustomMapStyleOptions()
.setEnable(true)
.setStyleData(MapAssetStyleUtils.getAssetsStyle(context, "over_view_style.data"))
.setStyleExtraData(
MapAssetStyleUtils.getAssetsExtraStyle(
context,
"over_view_style_extra.data"
)
)
// 设置自定义样式
mAMap?.setCustomMapStyle(customMapStyleOptions1)
mAMapNaviView!!.map.setPointToCenter(
mAMapNaviView!!.width / 2,
mAMapNaviView!!.height / 2
)
})
}
private fun startTask() {
val mTimer = Timer()
mTimer.schedule(UpdateLocationTask(), 1000, 200)
}
private inner class UpdateLocationTask : TimerTask() {
override fun run() {
if (mLocation != null) {
if (mCarMarker == null) {
mCarMarker = mAMap!!.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_my_location_logo))
.anchor(0.5f, 0.5f)
)
}
if (mCarMarker == null) {
return
}
val currentLatLng = LatLng(mLocation!!.latitude, mLocation!!.longitude)
val bearing = floor(mLocation!!.heading).toFloat()
//更新车辆位置
mCarMarker!!.position = currentLatLng
if (mCoordinatesLatLng.size > 1) {
// 结束位置
val endLatLng = mCoordinatesLatLng[mCoordinatesLatLng.size - 1]
val calculateDistance = CoordinateUtils.calculateLineDistance(
endLatLng.latitude, endLatLng.longitude,
currentLatLng.latitude, currentLatLng.longitude
)
CallerLogger.d(
SceneConstant.M_MAP + TAG,
"calculateDistance=$calculateDistance"
)
if (calculateDistance <= 5) {
clearPolyline()
mCoordinatesLatLng.clear()
}
}
val cameraPosition: CameraPosition =
CameraPosition.Builder().target(mCarMarker!!.position).tilt(0f).bearing(bearing)
.zoom(zoomLevel.toFloat()).build()
mAMap?.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
}
}
private fun coordinateConverterFrom84(mContext: Context?, mogoLatLng: MogoLatLng): LatLng {
val mCoordinateConverter = CoordinateConverter(mContext)
mCoordinateConverter.from(CoordinateConverter.CoordType.GPS)
mCoordinateConverter.coord(LatLng(mogoLatLng.lat, mogoLatLng.lon))
return mCoordinateConverter.convert()
}
private fun coordinateConverterFrom84ForList(
mContext: Context?,
mogoLatLngList: List<MogoLatLng>
): List<LatLng> {
val list: MutableList<LatLng> = ArrayList()
for (m in mogoLatLngList) {
val mogoLatLng = coordinateConverterFrom84(mContext, m)
list.add(mogoLatLng)
}
return list
}
override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) {
if (mogoLocation == null) {
return
}
mLocation = mogoLocation
}
override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) {
val tempStatus = autoPilotStatusInfo.pilotmode
if (tempStatus != 1) {
UiThreadHandler.post {
clearPolyline()
}
} else if (tempStatus == 1 && autoPilotStatus == 0) {
getGlobalPath()
}
autoPilotStatus = tempStatus
}
override fun onAutopilotRotting(globalPathResp: MessagePad.GlobalPathResp?) {
if (globalPathResp == null || globalPathResp.wayPointsList.size == 0) {
return
}
val latLngList: MutableList<MogoLatLng> = ArrayList()
for (routeModel in globalPathResp.wayPointsList) {
latLngList.add(MogoLatLng(routeModel.latitude, routeModel.longitude))
}
if (latLngList.size > 0) {
UiThreadHandler.post {
convert(latLngList)
drawablePolyline()
}
} else {
UiThreadHandler.post {
clearPolyline()
}
}
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
// 注册定位监听
CallerChassisLocationGCJ20ListenerManager.removeListener(TAG)
CallerPlanningRottingListenerManager.removeListener(TAG)
CallerAutoPilotStatusListenerManager.removeListener(TAG)
}
}