[6.7.0][Feat]小地图和全览地图动态切换

This commit is contained in:
chenfufeng
2024-09-24 18:02:39 +08:00
parent d08f1fcd60
commit 465a309704
5 changed files with 510 additions and 254 deletions

View File

@@ -22,6 +22,7 @@ import com.amap.api.maps.TextureMapView
import com.amap.api.maps.model.AMapGestureListener
import com.amap.api.maps.model.BitmapDescriptor
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.CameraPosition
import com.amap.api.maps.model.CustomMapStyleOptions
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.LatLngBounds
@@ -30,7 +31,9 @@ import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.Polyline
import com.amap.api.maps.model.PolylineOptions
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.business.travelreality.CrossDeviceBean
@@ -42,16 +45,23 @@ import com.mogo.eagle.core.function.business.travelreality.Point
import com.mogo.eagle.core.function.business.travelreality.TravelRealityModel.Companion.travelNetWorkModel
import com.mogo.eagle.core.function.business.travelreality.view.EventVideoView
import com.mogo.eagle.core.function.business.travelreality.view.VideoMarkerEntity
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.map.R
import com.mogo.eagle.core.function.smp.view.SmallMapView
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.CoordinateUtils
import com.mogo.eagle.core.utilcode.util.LocationUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
import me.jessyan.autosize.utils.AutoSizeUtils
import mogo.telematics.pad.MessagePad
import kotlin.math.floor
/**
* 行程实况View
@@ -63,7 +73,7 @@ class TravelRealityView @JvmOverloads constructor(
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr), IMoGoChassisLocationGCJ02Listener,
IMoGoPlanningRottingListener {
IMoGoPlanningRottingListener, IMoGoAutopilotStatusListener {
companion object {
private const val TAG = "TravelRealityView"
@@ -79,6 +89,7 @@ class TravelRealityView @JvmOverloads constructor(
private const val DRAW_LIVE_DETAIL = 9
private const val DRAW_END_MARKER = 10
private const val UPDATE_VIDEO_MARKER = 11
private const val HIDE_CAR_MARKER = 12
// private const val CLEAR_POLY_LINE = 12
// private const val CLEAR_ROAD_EVENT = 13
@@ -112,11 +123,11 @@ class TravelRealityView @JvmOverloads constructor(
private val globalPolylineList by lazy {
ArrayList<Polyline>()
}
private var mStartMarker: Marker? = null
private var mEndMarker: Marker? = null
@Volatile
private var mLocation: MogoLocation? = null
private var mStartMarker: Marker? = null
private var mEndMarker: Marker? = null
@Volatile
private var isMapLoaded = false
@@ -209,7 +220,19 @@ class TravelRealityView @JvmOverloads constructor(
private var listener: OnDrawListener? = null
private var gestureListener: OnGestureListener? = null
/**
* ====================小地图使用的====================
*/
@Volatile
private var isSmallMap: Boolean = true
private var iconRes = R.drawable.map_car_icon
private var globalPathResp: MessagePad.GlobalPathResp? = null
private val mCoordinatesLatLng: MutableList<LatLng> = ArrayList()
private var mSmallCarMarker: Marker? = null
private var mPolyline: Polyline? = null
private var mSmallStartMarker: Marker? = null
private var mSmallEndMarker: Marker? = null
init {
try {
@@ -285,6 +308,26 @@ class TravelRealityView @JvmOverloads constructor(
this.isSmallMap = isSmallMap
}
fun swapSettings() {
if (isSmallMap) {
Message.obtain().apply {
what = CLEAR_ALL_DATA
nonFrequentHandler?.sendMessage(this)
}
Message.obtain().apply {
what = HIDE_CAR_MARKER
nonFrequentHandler?.sendMessage(this)
}
// 显示小地图样式
changeMapSettings(true)
} else {
clearPolyline()
hideSmallCarMarker()
// 显示行程总览地图样式
changeMapSettings(false)
}
}
/**
* 清除所有Marker和Polyline
*/
@@ -310,7 +353,16 @@ class TravelRealityView @JvmOverloads constructor(
BitmapDescriptorFactory.fromResource(if (roadRangeDrawable != -1) roadRangeDrawable else R.drawable.mogo_road_over)
roadTrajectoryBitmap =
BitmapDescriptorFactory.fromResource(if (roadTrajectoryDrawable != -1) roadTrajectoryDrawable else R.drawable.road_trajectory_arrow_nor)
initAMapView()
// initTravelRealityMapView()
initSmallMapView(true)
}
private fun changeMapSettings(isSmallMap: Boolean) {
if (isSmallMap) {
initSmallMapView(false)
} else {
initTravelRealityMapView(false)
}
}
private fun getBitmap1(): Bitmap {
@@ -327,7 +379,83 @@ class TravelRealityView @JvmOverloads constructor(
return BitmapFactory.decodeResource(resources, R.drawable.count_bg, options)
}
private fun initAMapView() {
private fun initSmallMapView(isInit: Boolean) {
val cameraUpdate = CameraUpdateFactory.zoomTo(17f)
mAMap = mMapView?.map
// 关闭地图文字标注
mAMap?.showMapText(false)
// 设置导航地图模式aMap是地图控制器对象。
mAMap?.mapType = AMap.MAP_TYPE_NIGHT
// 关闭显示实时路况图层aMap是地图控制器对象。
mAMap?.isTrafficEnabled = false
// 设置 锚点 图标
if (isInit) {
iconRes = if (AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)) {
R.drawable.map_bus_icon
} else if (AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode) || AppIdentityModeUtils.isM1(FunctionBuildConfig.appIdentityMode)) {
R.drawable.map_m2_icon
} else {
R.drawable.map_car_icon
}
mSmallCarMarker = mAMap?.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(iconRes))
.anchor(0.5f, 0.5f)
)
mSmallStartMarker = mAMap?.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_dir_start))
)
mSmallEndMarker = 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(cameraUpdate)
// 设置地图的样式
val uiSettings = mAMap?.uiSettings
uiSettings?.isZoomControlsEnabled = false // 地图缩放级别的交换按钮
uiSettings?.setAllGesturesEnabled(false) // 所有手势
uiSettings?.isMyLocationButtonEnabled = false // 显示默认的定位按钮
uiSettings?.setLogoBottomMargin(-150) //设置Logo下边界距离屏幕底部的边距,设置为负值即可
if (isInit) {
mAMap?.setOnMapLoadedListener {
CallerLogger.d(
SceneConstant.M_MAP + SmallMapView.TAG,
"smp---onMapLoaded"
)
isMapLoaded = true
// 加载自定义样式
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)
}
mAMap?.setAMapGestureListener(gestListener)
}
}
private fun initTravelRealityMapView(isInit: Boolean = false) {
Log.d(TAG, "initAMapView")
mAMap = mMapView?.map
val mapStyleOptions = CustomMapStyleOptions()
@@ -343,23 +471,21 @@ class TravelRealityView @JvmOverloads constructor(
//设置希望展示的地图缩放级别
val loc = CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02()
if (loc.latitude.toInt() == 0 || loc.longitude.toInt() == 0) {
mAMap?.moveCamera(CameraUpdateFactory.zoomTo(14f))
moveMapCamera(CameraUpdateFactory.zoomTo(14f))
} else {
mAMap?.moveCamera(
CameraUpdateFactory.newLatLngZoom(
coordinateConverterWgsToGcj(
loc.latitude,
loc.longitude
), 14f
)
)
moveMapCamera(CameraUpdateFactory.newLatLngZoom(
coordinateConverterWgsToGcj(
loc.latitude,
loc.longitude
), 14f
))
}
//设置地图的样式
mAMap?.uiSettings?.let {
//所有手势
it.setAllGesturesEnabled(true)
//地图缩放级别的交换按钮
it.isZoomControlsEnabled = true
it.isZoomControlsEnabled = false
it.isZoomGesturesEnabled = true
//指南针
it.isCompassEnabled = false
@@ -368,53 +494,58 @@ class TravelRealityView @JvmOverloads constructor(
//定位按钮
it.isMyLocationButtonEnabled = false
//去掉高德Logo
it.setLogoBottomMargin(-100)
it.setLogoBottomMargin(-150)
}
mAMap?.setOnMapLoadedListener {
Log.d(TAG, "地图加载完成!")
isMapLoaded = true
mAMap?.setCustomMapStyle(mapStyleOptions)
// 实时路况图层关闭必须添加在loaded结束之后,其他位置不生效
mAMap?.isTrafficEnabled = false
mAMap?.showBuildings(false)
mAMap?.uiSettings?.isZoomControlsEnabled = false
if (isInit) {
mAMap?.setOnMapLoadedListener {
Log.d(TAG, "地图加载完成!")
isMapLoaded = true
mAMap?.setCustomMapStyle(mapStyleOptions)
// 实时路况图层关闭必须添加在loaded结束之后,其他位置不生效
mAMap?.isTrafficEnabled = false
mAMap?.showBuildings(false)
mAMap?.uiSettings?.isZoomControlsEnabled = false
// mAMap?.animateCamera(CameraUpdateFactory.changeTilt(30f))
}
mAMap?.setAMapGestureListener(gestListener)
}
mAMap?.setAMapGestureListener(object : AMapGestureListener {
override fun onDoubleTap(p0: Float, p1: Float) {
}
}
override fun onSingleTap(p0: Float, p1: Float) {
gestureListener?.onSingleTap(p0, p1)
}
private val gestListener = object : AMapGestureListener {
override fun onDoubleTap(p0: Float, p1: Float) {
}
override fun onFling(p0: Float, p1: Float) {
}
override fun onSingleTap(p0: Float, p1: Float) {
gestureListener?.onSingleTap(p0, p1)
}
override fun onScroll(p0: Float, p1: Float) {
}
override fun onFling(p0: Float, p1: Float) {
}
override fun onLongPress(p0: Float, p1: Float) {
}
override fun onScroll(p0: Float, p1: Float) {
}
override fun onDown(p0: Float, p1: Float) {
}
override fun onLongPress(p0: Float, p1: Float) {
}
override fun onUp(p0: Float, p1: Float) {
}
override fun onDown(p0: Float, p1: Float) {
}
override fun onMapStable() {
}
})
override fun onUp(p0: Float, p1: Float) {
}
override fun onMapStable() {
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
if (isSmallMap) {
this.outlineProvider = TextureVideoViewOutlineProvider(AutoSizeUtils.dp2px(context, 32f)
.toFloat())
this.outlineProvider = TextureVideoViewOutlineProvider(
AutoSizeUtils.dp2px(context, 32f)
.toFloat()
)
this.clipToOutline = true
} else {
this.clipToOutline = false
@@ -441,6 +572,7 @@ class TravelRealityView @JvmOverloads constructor(
CallerPlanningRottingListenerManager.addListener("${TAG}${this.hashCode()}", this)
// 注册定位监听
CallerChassisLocationGCJ02ListenerManager.addListener("${TAG}${this.hashCode()}", this)
CallerAutoPilotStatusListenerManager.addListener("${TAG}${this.hashCode()}", this)
}
override fun onDetachedFromWindow() {
@@ -944,9 +1076,14 @@ class TravelRealityView @JvmOverloads constructor(
globalList[index + 1].lat
)
// 深拷贝一下数据
deviceInPaths.add(DeviceInfoBean(deviceBean.deviceIp, deviceBean.lon, deviceBean.lat).also { deviceInfo ->
deviceInfo.orientation = deviceBean.orientation
})
deviceInPaths.add(
DeviceInfoBean(
deviceBean.deviceIp,
deviceBean.lon,
deviceBean.lat
).also { deviceInfo ->
deviceInfo.orientation = deviceBean.orientation
})
crossOptionsList.add(MarkerOptions().apply {
position(
coordinateConverterWgsToGcj(
@@ -1235,10 +1372,14 @@ class TravelRealityView @JvmOverloads constructor(
override fun onChassisLocationGCJ02(gnssInfo: MogoLocation?) {
gnssInfo?.let {
mLocation = it
if (isMapLoaded) {
// 绘制自车
drawCarMarker(it)
if (!isSmallMap) {
mLocation = it
if (isMapLoaded) {
// 绘制自车
drawCarMarker(it)
}
} else {
drawSmallMapMarker(it)
}
}
}
@@ -1252,26 +1393,193 @@ class TravelRealityView @JvmOverloads constructor(
}
Log.d(TAG, "下发全局轨迹!")
globalPathResp?.let { globalPath ->
// nonFrequentHandler?.removeCallbacksAndMessages(null)
if (isSmallMap) {
if (globalPath.wayPointsList.size > 0) {
this.globalPathResp = globalPath
drawRotting()
}
} else {
val pointList = ArrayList<Point>()
val pointCloneList = ArrayList<Point>()
globalPath.wayPointsList.forEach { loc ->
pointList.add(Point(loc.longitude, loc.latitude))
pointCloneList.add(Point(loc.longitude, loc.latitude))
}
Log.d(TAG, "轨迹点个数为:${pointList.size}")
reqData = pointCloneList
handleGlobalPath(pointList)
val pointList = ArrayList<Point>()
val pointCloneList = ArrayList<Point>()
globalPath.wayPointsList.forEach { loc ->
pointList.add(Point(loc.longitude, loc.latitude))
pointCloneList.add(Point(loc.longitude, loc.latitude))
}
Log.d(TAG, "轨迹点个数为:${pointList.size}")
reqData = pointCloneList
handleGlobalPath(pointList)
requestData(pointList)
if (!isRoadTrackReq) {
Log.d(TAG, "处理智慧道路轨迹!")
handleRoadTrajectories(roadTrackList, pointList)
requestData(pointList)
if (!isRoadTrackReq) {
Log.d(TAG, "处理智慧道路轨迹!")
handleRoadTrajectories(roadTrackList, pointList)
}
}
}
}
//===================================小地图绘制起始!===================================
override fun onAutopilotStatusResponse(state: Int) {
if (isSmallMap) {
if (state == 2) {
drawRotting()
} else {
UiThreadHandler.post {
clearPolyline()
}
}
}
}
private fun drawRotting() {
globalPathResp?.let {
val latLngList: MutableList<MogoLatLng> = ArrayList()
for (routeModel in globalPathResp!!.wayPointsList) {
latLngList.add(MogoLatLng(routeModel.latitude, routeModel.longitude))
}
CallerLogger.d(
SceneConstant.M_MAP + SmallMapView.TAG,
"SmallMapView latLngList.size = ${latLngList.size}"
)
if (latLngList.size > 0) {
UiThreadHandler.post {
convert(latLngList)
drawablePolyline()
}
} else {
UiThreadHandler.post {
CallerLogger.d(
SceneConstant.M_MAP + SmallMapView.TAG,
"SmallMapView latLngList.size = ${latLngList.size} clearPolyline ---->"
)
clearPolyline()
}
}
}
}
private fun convert(coordinates: List<MogoLatLng>) {
mCoordinatesLatLng.clear()
val latLngs = coordinateConverterFrom84ForList(mContext, coordinates)
mCoordinatesLatLng.addAll(latLngs)
}
private fun drawablePolyline() {
clearPolyline()
if (mAMap != null) {
if (mCoordinatesLatLng.size >= 2) {
// 设置开始结束Marker位置
mSmallStartMarker!!.position = mCoordinatesLatLng[0]
mSmallEndMarker!!.position = mCoordinatesLatLng[mCoordinatesLatLng.size - 1]
mSmallStartMarker!!.setToTop()
mSmallStartMarker!!.isVisible = true
mSmallEndMarker!!.isVisible = true
mSmallEndMarker!!.setToTop()
//存放所有点的经纬度
val boundsBuilder = LatLngBounds.Builder()
for (i in mCoordinatesLatLng.indices) {
//把所有点都include进去LatLng类型
boundsBuilder.include(mCoordinatesLatLng[i])
}
//第二个参数为四周留空宽度
mAMap!!.animateCamera(
CameraUpdateFactory.newLatLngBounds(
boundsBuilder.build(),
30
)
)
// 绘制线
mPolyline?.points = mCoordinatesLatLng
CallerLogger.d(
SceneConstant.M_MAP + SmallMapView.TAG,
"SmallMapView drawPolyline size is = ${mCoordinatesLatLng.size} "
)
}
}
}
private fun clearPolyline() {
if (mPolyline != null) {
mPolyline!!.points = emptyList()
}
if (mSmallStartMarker != null) {
mSmallStartMarker!!.isVisible = false
}
if (mSmallEndMarker != null) {
mSmallEndMarker!!.isVisible = false
}
}
private fun hideSmallCarMarker() {
mSmallCarMarker?.isVisible = false
}
private fun drawSmallMapMarker(mogoLocation: MogoLocation) {
mLocation = mogoLocation
if (mSmallCarMarker == null) {
mSmallCarMarker = mAMap?.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(iconRes))
.anchor(0.5f, 0.5f)
)
}
if (mSmallCarMarker == null) {
return
}
UiThreadHandler.post {
val currentLatLng = LatLng(mLocation!!.latitude, mLocation!!.longitude)
val bearing = floor(mLocation!!.heading).toFloat()
//更新车辆位置
mSmallCarMarker!!.position = currentLatLng
mSmallCarMarker!!.isVisible = true
if (mCoordinatesLatLng.size > 1) {
// 结束位置
val endLatLng = mCoordinatesLatLng[mCoordinatesLatLng.size - 1]
val calculateDistance = CoordinateUtils.calculateLineDistance(
endLatLng.latitude, endLatLng.longitude,
currentLatLng.latitude, currentLatLng.longitude
)
if (calculateDistance <= 5) {
CallerLogger.d(
SceneConstant.M_MAP + SmallMapView.TAG,
"onChassisLocationGCJ02 -----> calculateDistance <= 5 "
)
clearPolyline()
mCoordinatesLatLng.clear()
}
}
val cameraPosition: CameraPosition =
CameraPosition.Builder()
.target(mSmallCarMarker!!.position)
.tilt(0f)
.bearing(bearing)
.zoom(17f)
.build()
mAMap?.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
}
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
}
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 requestData(pointList: ArrayList<Point>) {
if (!isCrossDeviceReq) {
Log.d(TAG, "请求获取路口设备!")
@@ -1356,6 +1664,11 @@ class TravelRealityView @JvmOverloads constructor(
realDrawCar(this)
}
}
HIDE_CAR_MARKER -> {
removeMessages(HIDE_CAR_MARKER)
if (isMapDestroyed) return
hideCarMarker()
}
DRAW_POLY_LINE -> {
removeMessages(DRAW_POLY_LINE)
@@ -1475,6 +1788,7 @@ class TravelRealityView @JvmOverloads constructor(
val latLng = LatLng(location.latitude, location.longitude)
val angle = (360 - location.heading).toFloat()
if (mCarMarker != null) {
mCarMarker!!.isVisible = true
mCarMarker!!.rotateAngle = angle
mCarMarker!!.position = latLng
} else {
@@ -1488,6 +1802,7 @@ class TravelRealityView @JvmOverloads constructor(
// mCarMarker?.setToTop()
}
if (mCompassMarker != null) {
mCompassMarker!!.isVisible = true
mCompassMarker!!.rotateAngle = angle
mCompassMarker!!.position = latLng
} else {
@@ -1500,6 +1815,11 @@ class TravelRealityView @JvmOverloads constructor(
}
}
private fun hideCarMarker() {
mCarMarker?.isVisible = false
mCompassMarker?.isVisible = false
}
private fun realDrawGlobalPath(polylineOptions: PolylineOptions) {
Log.d(TAG, "realDrawGlobalPath")
if (globalPolyline == null) {