[6.5.0][Opt]优化行程总览UI效果

This commit is contained in:
chenfufeng
2024-07-09 20:25:32 +08:00
parent 03ca894088
commit df512827e2
9 changed files with 263 additions and 32 deletions

View File

@@ -0,0 +1,7 @@
package com.mogo.eagle.core.function.business.travelreality
data class EventReqEntity(
var points: List<Point>,
var cityCode: String = "0734",
var adCode: String = ""
)

View File

@@ -1,5 +1,14 @@
package com.mogo.eagle.core.function.business.travelreality
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import com.amap.api.maps.model.LatLng
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.GranularRoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.mogo.commons.constants.HostConst
import com.mogo.eagle.core.data.BaseResponse
import com.mogo.eagle.core.data.Response
@@ -9,9 +18,8 @@ import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.network.apiCall
import com.mogo.eagle.core.network.apiResponseCall
import com.mogo.eagle.core.network.request
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.Md5Util
import retrofit2.http.Query
import me.jessyan.autosize.utils.AutoSizeUtils
import java.util.Locale
class TravelRealityModel private constructor() {
@@ -30,7 +38,7 @@ class TravelRealityModel private constructor() {
/**
* 查询道路事件
*/
fun getEventsWithTrajRequest(reqData: List<Point>,
fun getEventsWithTrajRequest(reqData: EventReqEntity,
onSuccess: ((List<EventBean>) -> Unit), onError: ((String) -> Unit)){
request<Response<List<EventBean>?>>{
loader {
@@ -60,7 +68,7 @@ class TravelRealityModel private constructor() {
val md5String = "${CROSS_DEVICE.uppercase(Locale.getDefault())}$time"
val loc = CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
val cityCode = CallerMapUIServiceManager.getCityCode() ?: "0734"
getNetWorkApi(HostConst.getNDEHost()).getCrossDevice(Md5Util.getMD5Result(md5String), time, "", loc.longitude, loc.latitude, "0734")
getNetWorkApi(HostConst.getNDEHost()).getCrossDevice(Md5Util.getMD5Result(md5String), time, "", loc.longitude, loc.latitude, cityCode)
}
}
onSuccess {
@@ -83,7 +91,7 @@ class TravelRealityModel private constructor() {
val md5String = "${CITY_ROAD_RANGE.uppercase(Locale.getDefault())}$time"
val loc = CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
val cityCode = CallerMapUIServiceManager.getCityCode() ?: "0734"
getNetWorkApi(HostConst.getNDEHost()).getCityRoadRange(Md5Util.getMD5Result(md5String), time, loc.longitude, loc.latitude, "0734")
getNetWorkApi(HostConst.getNDEHost()).getCityRoadRange(Md5Util.getMD5Result(md5String), time, loc.longitude, loc.latitude, cityCode)
}
}
onSuccess {
@@ -106,7 +114,7 @@ class TravelRealityModel private constructor() {
val md5String = "${CITY_ROAD_TRACK.uppercase(Locale.getDefault())}$time"
val loc = CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
val cityCode = CallerMapUIServiceManager.getCityCode() ?: "0734"
getNetWorkApi(HostConst.getNDEHost()).getCityRoadTrack(Md5Util.getMD5Result(md5String), time, loc.longitude, loc.latitude, "0734")
getNetWorkApi(HostConst.getNDEHost()).getCityRoadTrack(Md5Util.getMD5Result(md5String), time, loc.longitude, loc.latitude, cityCode)
}
}
onSuccess {
@@ -117,4 +125,32 @@ class TravelRealityModel private constructor() {
}
}
}
fun downloadImage(context: Context, url: String?,
latLng: LatLng,
onSuccess: ((Bitmap, LatLng) -> Unit),
onFailed: ((LatLng) -> Unit)
) {
if (url.isNullOrEmpty()) return
val radiusPx = AutoSizeUtils.dp2px(context, 15f).toFloat()
val options = RequestOptions().transform(
GranularRoundedCorners(radiusPx, radiusPx,0f,0f)
)
Glide.with(context)
.asBitmap()
.apply(options)
.load(url)
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
onSuccess(resource, latLng)
}
override fun onLoadCleared(placeholder: Drawable?) {}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
onFailed(latLng)
}
})
}
}

View File

@@ -24,7 +24,7 @@ interface TravelRealityService {
suspend fun getEventsWithTrajRequest(
@Header("MogoAuthKey") authKey: String,
@Header("MogoReqTime") time: String,
@Body reqData: List<Point>
@Body reqData: EventReqEntity
): Response<List<EventBean>>
/**

View File

@@ -0,0 +1,48 @@
package com.mogo.eagle.core.function.business.travelreality.view
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.eagle.core.function.map.R
@SuppressLint("ViewConstructor")
class EventVideoView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
private val title: String? = "全息路口"
) : ConstraintLayout (
context,
attrs,
defStyleAttr
) {
init {
LayoutInflater.from(context).inflate(R.layout.layout_event_video_maker, this, true)
initView()
}
private lateinit var videoImgView: ImageView
private fun initView() {
videoImgView = findViewById(R.id.videoImg)
val titleView = findViewById<TextView>(R.id.tvTitle)
title?.let {
titleView.text = it
}
}
fun setBitmap(bitmap: Bitmap) {
videoImgView.setImageBitmap(bitmap)
}
fun setPlaceHolder() {
videoImgView.setImageResource(R.drawable.video_marker_place_holder)
}
}

View File

@@ -32,13 +32,16 @@ import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Liste
import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener
import com.mogo.eagle.core.function.business.roadcross.net.NDERoadCameraNetWorkModel.Companion.ndeRoadCameraNetWorkModel
import com.mogo.eagle.core.function.business.travelreality.CrossDeviceBean
import com.mogo.eagle.core.function.business.travelreality.DeviceInfoBean
import com.mogo.eagle.core.function.business.travelreality.EventBean
import com.mogo.eagle.core.function.business.travelreality.EventReqEntity
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.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.V2XMarkerView
import com.mogo.eagle.core.utilcode.mogo.MapAssetStyleUtils
import com.mogo.eagle.core.utilcode.util.LocationUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
@@ -57,6 +60,29 @@ class TravelRealityView @JvmOverloads constructor(
) : ConstraintLayout(context, attrs, defStyleAttr), IMoGoChassisLocationGCJ02Listener,
IMoGoPlanningRottingListener {
companion object {
private const val TAG = "TravelRealityView"
private const val DRAW_POLY_LINE = 1
private const val DRAW_CAR_LOCATION = 2
private const val DRAW_ROAD_EVENT = 3
private const val DRAW_CROSS_DEVICE = 4
private const val DRAW_ROAD_RANGE = 5
private const val DRAW_ROAD_TRAJECTORY = 6
private const val DRAW_GLOBAL_TRAJECTORY = 7
private const val MOVE_MAP_CAMERA = 8
private const val DRAW_LIVE_DETAIL = 9
private const val DRAW_END_MARKER = 10
private const val UPDATE_VIDEO_MARKER = 11
private const val maxRoadRange = 68f
private const val minRoadRange = 52f
private const val maxRoadWidth = 32f
private const val minRoadWidth = 14f
private const val maxGlobalWidth = 20f
private const val minGlobalWidth = 13f
}
private var mContext: Context? = null
private var mMapView: TextureMapView? = null
@@ -109,6 +135,14 @@ class TravelRealityView @JvmOverloads constructor(
private val roadTrajectoryBitmap by lazy {
BitmapDescriptorFactory.fromResource(R.drawable.mogo_road_over)
}
@Volatile
private var roadRange = minRoadRange
@Volatile
private var roadWidth = minRoadWidth
@Volatile
private var globalWidth = minGlobalWidth
// // 测试时使用
// private val pointBitmap1 by lazy {
@@ -141,6 +175,8 @@ class TravelRealityView @JvmOverloads constructor(
@Volatile
private var deviceList: List<CrossDeviceBean>? = null
@Volatile
private var deviceInPathList: List<CrossDeviceBean>? = null
@Volatile
private var roadTrackList: List<List<List<Double>?>?>? = null
@@ -157,21 +193,6 @@ class TravelRealityView @JvmOverloads constructor(
private var testTime = 0L
companion object {
private const val TAG = "TravelRealityView"
private const val DRAW_POLY_LINE = 1
private const val DRAW_CAR_LOCATION = 2
private const val DRAW_ROAD_EVENT = 3
private const val DRAW_CROSS_DEVICE = 4
private const val DRAW_ROAD_RANGE = 5
private const val DRAW_ROAD_TRAJECTORY = 6
private const val DRAW_GLOBAL_TRAJECTORY = 7
private const val MOVE_MAP_CAMERA = 8
private const val DRAW_LIVE_DETAIL = 9
private const val DRAW_END_MARKER = 10
}
init {
try {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.TravelRealityView)
@@ -334,7 +355,7 @@ class TravelRealityView @JvmOverloads constructor(
val boundsBuilder = LatLngBounds.Builder()
val globalOptions = PolylineOptions()
globalOptions.width(AutoSizeUtils.dp2px(context, 20f).toFloat())
globalOptions.width(AutoSizeUtils.dp2px(context, globalWidth).toFloat())
globalOptions.lineJoinType(PolylineOptions.LineJoinType.LineJoinRound)
globalOptions.lineCapType(PolylineOptions.LineCapType.LineCapRound)
globalOptions.color(globalPathColor)
@@ -371,6 +392,23 @@ class TravelRealityView @JvmOverloads constructor(
// mAMap?.addMarkers(markerOptionsList1, false)
val distance = LocationUtils.getDistance(
globalData[globalData.size - 1].lat,
globalData[globalData.size - 1].lon,
globalData[0].lat,
globalData[0].lon
)
Log.w(TAG, "起终点距离为:$distance")
if (distance < 2000) {
roadRange = maxRoadRange
roadWidth = maxRoadWidth
globalWidth = maxGlobalWidth
} else {
roadRange = minRoadRange
roadWidth = minRoadWidth
globalWidth = minGlobalWidth
}
val endOption = MarkerOptions()
endOption.icon(BitmapDescriptorFactory.fromResource(endPointDrawable))
endOption.position(
@@ -450,6 +488,7 @@ class TravelRealityView @JvmOverloads constructor(
eventOptionsList.add(MarkerOptions().apply {
position(coordinateConverterWgsToGcj(eventBean.lat, eventBean.lon))
anchor(0.5f, 0.5f)
zIndex(0.8f)
icon(BitmapDescriptorFactory.fromResource(R.drawable.mogo_shigu_nor))
})
roadEventList.add(eventBean)
@@ -459,6 +498,7 @@ class TravelRealityView @JvmOverloads constructor(
eventOptionsList.add(MarkerOptions().apply {
position(coordinateConverterWgsToGcj(eventBean.lat, eventBean.lon))
anchor(0.5f, 0.5f)
zIndex(0.8f)
icon(BitmapDescriptorFactory.fromResource(R.drawable.mogo_shigong_image))
})
roadEventList.add(eventBean)
@@ -468,6 +508,7 @@ class TravelRealityView @JvmOverloads constructor(
eventOptionsList.add(MarkerOptions().apply {
position(coordinateConverterWgsToGcj(eventBean.lat, eventBean.lon))
anchor(0.5f, 0.5f)
zIndex(0.8f)
icon(BitmapDescriptorFactory.fromResource(R.drawable.mogo_yongdu_nor))
})
}
@@ -476,6 +517,7 @@ class TravelRealityView @JvmOverloads constructor(
eventOptionsList.add(MarkerOptions().apply {
position(coordinateConverterWgsToGcj(eventBean.lat, eventBean.lon))
anchor(0.5f, 0.5f)
zIndex(0.8f)
icon(BitmapDescriptorFactory.fromResource(R.drawable.mogo_jingzhi_nor))
})
roadEventList.add(eventBean)
@@ -485,6 +527,7 @@ class TravelRealityView @JvmOverloads constructor(
eventOptionsList.add(MarkerOptions().apply {
position(coordinateConverterWgsToGcj(eventBean.lat, eventBean.lon))
anchor(0.5f, 0.5f)
zIndex(0.8f)
icon(BitmapDescriptorFactory.fromResource(R.drawable.mogo_jingzhi_nor))
})
roadEventList.add(eventBean)
@@ -493,7 +536,7 @@ class TravelRealityView @JvmOverloads constructor(
}
private fun retryGetCrossDevice() {
val crossDeviceListTmp = deviceList
val crossDeviceListTmp = deviceInPathList
if (crossDeviceListTmp.isNullOrEmpty()) {
if (retryCount >= 5) return
retryCount++
@@ -507,6 +550,7 @@ class TravelRealityView @JvmOverloads constructor(
roadEventList.forEach {
ipList.add(it.ip ?: "")
}
// 轨迹线附近的路口设备取几个进行卡片展示
for (i in crossDeviceListTmp.indices) {
if (maxSize > 0 && !crossDeviceListTmp[i].deviceInfoList.isNullOrEmpty()) {
crossDeviceListTmp[i].deviceInfoList!![0].deviceIp?.let {
@@ -523,16 +567,36 @@ class TravelRealityView @JvmOverloads constructor(
}
}
/**
* 先下载图片然后设置给View
* 再转换成BitmapDescriptor最后进行渲染
*/
private fun downloadImage(url: String, latLng: LatLng?) {
if (latLng == null) return
travelNetWorkModel.downloadImage(context, url, latLng, onSuccess = { bitmap, latLng ->
val view = EventVideoView(context)
view.setBitmap(bitmap)
updateVideoMarker(view, latLng)
}, onFailed = {
val view = EventVideoView(context)
view.setPlaceHolder()
updateVideoMarker(view, latLng)
})
}
private fun reqCrossLive(ipList: MutableList<String>) {
ndeRoadCameraNetWorkModel.batchRequestCrossLive(ipList, onSuccess = {
val liveOptionsList = ArrayList<MarkerOptions>()
var markerOption: MarkerOptions
it.forEach { roadCamera ->
roadCamera.ip?.let { ip ->
roadCamera.imageUrl?.let { url ->
downloadImage(url, ipPointMap[ip])
}
markerOption = MarkerOptions()
markerOption.position(ipPointMap[ip])
markerOption.anchor(0.5f, 0.5f)
markerOption.icon(BitmapDescriptorFactory.fromView(V2XMarkerView(context)))
markerOption.zIndex(0.9f)
liveOptionsList.add(markerOption)
}
}
@@ -548,6 +612,7 @@ class TravelRealityView @JvmOverloads constructor(
if (crossDeviceList.isEmpty()) return
val crossOptionsList = ArrayList<MarkerOptions>()
val globalList = reqData
val deviceInPaths = ArrayList<DeviceInfoBean>()
globalList?.forEachIndexed { index, globalPoint ->
if (index >= 0 && index < globalList.size - 1) {
crossDeviceList.forEach {
@@ -563,7 +628,7 @@ class TravelRealityView @JvmOverloads constructor(
) {
return@loop
}
deviceInPaths.add(deviceBean)
crossOptionsList.add(MarkerOptions().apply {
position(
coordinateConverterWgsToGcj(
@@ -578,6 +643,7 @@ class TravelRealityView @JvmOverloads constructor(
}
}
}
deviceInPathList = arrayListOf(CrossDeviceBean("", 0.0, "", 0.0, deviceInPaths))
// 绘制路口设备
drawMarkers(DRAW_CROSS_DEVICE, crossOptionsList)
}
@@ -616,7 +682,7 @@ class TravelRealityView @JvmOverloads constructor(
val options = PolylineOptions()
trajectoryList?.forEach loop@{ trajPointList ->
if (trajPointList.isNullOrEmpty() || trajPointList.size < 2) return@loop
options.width(AutoSizeUtils.dp2px(context, 52f).toFloat())
options.width(AutoSizeUtils.dp2px(context, minRoadRange).toFloat())
options.isUseTexture = true
options.lineJoinType(PolylineOptions.LineJoinType.LineJoinRound)
options.lineCapType(PolylineOptions.LineCapType.LineCapSquare)
@@ -684,7 +750,11 @@ class TravelRealityView @JvmOverloads constructor(
// 绘制新的智慧路段轨迹
polylineOptionTmp = PolylineOptions()
polylineOptionTmp?.let { optionTmp ->
buildPolylineOption(optionTmp, 52f, roadTrajectoryBitmap)
buildPolylineOption(
optionTmp,
roadRange,
roadTrajectoryBitmap
)
optionTmp.add(
coordinateConverterWgsToGcj(
trajPointList[1],
@@ -737,7 +807,8 @@ class TravelRealityView @JvmOverloads constructor(
if (lastIndex < 0 || index - lastIndex > 1) {
globalOptionList.add(PolylineOptions().also {
optionTmp = it
buildPolylineOptionWithColor(it, 30f, roadTrajectoryColor)
buildPolylineOptionWithColor(it, roadWidth, roadTrajectoryColor)
it.add(coordinateConverterWgsToGcj(point.lat, point.lon))
})
} else {
optionTmp?.add(coordinateConverterWgsToGcj(point.lat, point.lon))
@@ -792,6 +863,18 @@ class TravelRealityView @JvmOverloads constructor(
}
}
private fun updateVideoMarker(view: EventVideoView, latLng: LatLng?) {
if (latLng == null) return
val options = MarkerOptions()
options.position(latLng)
options.icon(BitmapDescriptorFactory.fromView(view))
Message.obtain().apply {
what = UPDATE_VIDEO_MARKER
obj = options
nonFrequentHandler?.sendMessage(this)
}
}
private fun drawMarkers(type: Int, optionList: ArrayList<MarkerOptions>) {
Message.obtain().apply {
what = type
@@ -869,7 +952,8 @@ class TravelRealityView @JvmOverloads constructor(
Log.d(TAG, "Cross device error is:$it")
})
// 获取道路事件
travelNetWorkModel.getEventsWithTrajRequest(reqData!!, onSuccess = {
val cityCode = CallerMapUIServiceManager.getCityCode() ?: "0734"
travelNetWorkModel.getEventsWithTrajRequest(EventReqEntity(pointList, cityCode), onSuccess = {
Log.d(TAG, "Events result is:$it")
handleRoadEvent(it)
}, onError = {
@@ -943,7 +1027,7 @@ class TravelRealityView @JvmOverloads constructor(
DRAW_LIVE_DETAIL -> {
removeMessages(DRAW_LIVE_DETAIL)
(msg.obj as ArrayList<MarkerOptions>).apply {
// realDrawLiveMarkers(this)
realDrawLiveMarkers(this)
}
}
@@ -951,6 +1035,10 @@ class TravelRealityView @JvmOverloads constructor(
removeMessages(DRAW_END_MARKER)
realDrawEndMarker(msg.obj as MarkerOptions)
}
UPDATE_VIDEO_MARKER -> {
realUpdateVideoMarker(msg.obj as MarkerOptions)
}
}
} catch (e: Exception) {
e.printStackTrace()
@@ -1077,6 +1165,14 @@ class TravelRealityView @JvmOverloads constructor(
}
}
private fun realUpdateVideoMarker(options: MarkerOptions) {
liveMarkerList.forEach {
if (it.position == options.position) {
it.setIcon(options.icon)
}
}
}
private fun realDrawEndMarker(options: MarkerOptions) {
mEndMarker?.destroy()
if (endPointDrawable != -1) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="280dp"
android:layout_height="352dp"
android:background="@drawable/event_video_bg"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/videoImg"
android:layout_width="240dp"
android:layout_height="200dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="66dp"
/>
<TextView
android:id="@+id/tvTitle"
android:layout_width="152dp"
android:layout_height="36dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:gravity="center"
android:textStyle="bold"
android:layout_marginBottom="65dp"
tools:text="全息路口"
android:textColor="#132A54"
android:textSize="25dp"
/>
<ImageView
android:layout_width="88dp"
android:layout_height="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@drawable/event_logo_icon"
android:layout_marginBottom="40dp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>