[Opt]高德的小地图封装到View中
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user