[8.1.0]
[fea] [m2] [mogomind]
@@ -0,0 +1,64 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind
|
||||
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
||||
|
||||
object AIMessageManager {
|
||||
|
||||
// 使用 CopyOnWriteArrayList 来存储消息回调列表,保证线程安全
|
||||
private val messageListeners: MutableList<AIMessageListener> = CopyOnWriteArrayList()
|
||||
|
||||
|
||||
/**
|
||||
* 注册一个消息监听器。
|
||||
*
|
||||
* @param listener 要注册的 AiMessageListener 实例。
|
||||
*/
|
||||
fun registerListener(listener: AIMessageListener) {
|
||||
messageListeners.add(listener)
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消注册一个消息监听器。
|
||||
*
|
||||
* @param listener 要取消注册的 AiMessageListener 实例。
|
||||
*/
|
||||
fun unregisterListener(listener: AIMessageListener) {
|
||||
messageListeners.remove(listener)
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布一条消息。
|
||||
*
|
||||
* 这条消息会被发送给所有已注册的监听器。
|
||||
*
|
||||
* @param msg 要发布的消息。
|
||||
*/
|
||||
fun post(msg: AIMessage) {
|
||||
// 遍历所有已注册的监听器,并调用它们的 onReceive 方法
|
||||
messageListeners.forEach { callback ->
|
||||
callback.onReceive(msg)
|
||||
}
|
||||
}
|
||||
|
||||
fun clearData(){
|
||||
messageListeners.forEach { callback ->
|
||||
callback.clear()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息监听器接口。
|
||||
*/
|
||||
interface AIMessageListener {
|
||||
/**
|
||||
* 当接收到消息时,会调用此方法。
|
||||
*
|
||||
* @param msg 接收到的消息。
|
||||
*/
|
||||
fun onReceive(msg: AIMessage)
|
||||
|
||||
fun clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||
import androidx.lifecycle.findViewTreeViewModelStoreOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerRoadV2NEventWindowListenerManager
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager
|
||||
import com.mogo.eagle.core.utilcode.kotlin.onClick
|
||||
import com.mogo.eagle.core.utilcode.util.UriUtils
|
||||
import com.mogo.och.shuttle.weaknet.passenger.R
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo.LineViewModel
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter.AIMessageAdapter
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter.OnItemClickListener
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter.PaddingItemDecoration
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.data.AutomaticExplorationViewModel
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.data.NDEViewModel
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.data.RoadCrossRoamViewModel
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.data.RoadV2NEventViewModel
|
||||
import kotlinx.android.synthetic.main.m2_mind_view.view.rv_mind_list
|
||||
import kotlinx.android.synthetic.main.m2_mind_view.view.test1
|
||||
import kotlinx.android.synthetic.main.m2_mind_view.view.test2
|
||||
import kotlinx.android.synthetic.main.m2_mind_view.view.test3
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MindView : ConstraintLayout, MindViewModel.AiViewCallback {
|
||||
|
||||
private val TAG = "MindView"
|
||||
|
||||
constructor(context: Context) : super(context)
|
||||
|
||||
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
|
||||
|
||||
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
|
||||
|
||||
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
|
||||
|
||||
private var roadV2NEventModel: RoadV2NEventViewModel?= null
|
||||
private var roadCrossRoamModel: RoadCrossRoamViewModel?= null
|
||||
private var automaticExplorationModel: AutomaticExplorationViewModel?= null
|
||||
private var ndeViewModel: NDEViewModel?= null
|
||||
|
||||
|
||||
private var viewModel:MindViewModel?=null
|
||||
|
||||
private var isUserScrollingTime = 0L
|
||||
|
||||
private val SCROLL_THRESHOLD = 2000L
|
||||
|
||||
private val messageAdapter: AIMessageAdapter by lazy { AIMessageAdapter() }
|
||||
private val messageLayoutManager: LinearLayoutManager by lazy {
|
||||
LinearLayoutManager(context).apply {
|
||||
stackFromEnd = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
LayoutInflater.from(context).inflate(R.layout.m2_mind_view, this, true)
|
||||
|
||||
rv_mind_list.layoutManager = messageLayoutManager
|
||||
rv_mind_list.adapter = messageAdapter
|
||||
rv_mind_list.addItemDecoration(PaddingItemDecoration(200, 300))
|
||||
messageAdapter.onItemClickListener = OnItemClickListener { item, position ->
|
||||
if (item is AIMessage.Event) {
|
||||
|
||||
}
|
||||
}
|
||||
rv_mind_list.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
if (newState != RecyclerView.SCROLL_STATE_IDLE) {
|
||||
isUserScrollingTime = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test1.onClick {
|
||||
CallerRoadV2NEventWindowListenerManager.showImage(
|
||||
System.currentTimeMillis().toString(),
|
||||
System.currentTimeMillis(),
|
||||
EventTypeEnumNew.getUpdateIconRes(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
|
||||
String.format(
|
||||
EventTypeEnumNew.getAlarmContent(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
|
||||
100
|
||||
),
|
||||
false,
|
||||
EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
|
||||
UriUtils.res2Uri(
|
||||
EventTypeEnumNew.getPoiTypeBg(
|
||||
EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType,
|
||||
false
|
||||
).toString()
|
||||
).toString()
|
||||
)
|
||||
}
|
||||
test2.onClick {
|
||||
CallerMapRoadListenerManager.invokeCrossDevice(true)
|
||||
}
|
||||
test3.onClick {
|
||||
val one = AIMessage.RoadMsg(201,1,true,false)
|
||||
val two = AIMessage.RoadMsg(202,2,false,false)
|
||||
val three = AIMessage.RoadMsg(203,3,false,true)
|
||||
|
||||
val sortedList = ArrayList<AIMessage.RoadMsg>()
|
||||
sortedList.add(one)
|
||||
sortedList.add(two)
|
||||
sortedList.add(three)
|
||||
val ndeEvent = AIMessage.NDEData(System.currentTimeMillis().toString(),"路口车龙","前方路口有车龙",sortedList)
|
||||
AIMessageManager.post(ndeEvent)
|
||||
|
||||
// CallerRoadV2NEventWindowListenerManager.showImage(
|
||||
// System.currentTimeMillis().toString(),
|
||||
// System.currentTimeMillis(),
|
||||
// EventTypeEnumNew.getUpdateIconRes(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
|
||||
// String.format(
|
||||
// EventTypeEnumNew.getAlarmContent(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
|
||||
// 100
|
||||
// ),
|
||||
// false,
|
||||
// String.format(
|
||||
// EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
|
||||
// 100
|
||||
// ),
|
||||
// UriUtils.res2Uri(
|
||||
// EventTypeEnumNew.getPoiTypeBg(
|
||||
// EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType,
|
||||
// false
|
||||
// ).toString()
|
||||
// ).toString()
|
||||
// )
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
viewModel = findViewTreeViewModelStoreOwner()?.let {
|
||||
ViewModelProvider(it).get(MindViewModel::class.java)
|
||||
}
|
||||
viewModel?.setViewCallback(this)
|
||||
|
||||
roadV2NEventModel = findViewTreeViewModelStoreOwner()?.let{
|
||||
ViewModelProvider(it)[RoadV2NEventViewModel::class.java]
|
||||
}
|
||||
roadV2NEventModel?.init()
|
||||
roadCrossRoamModel = findViewTreeViewModelStoreOwner()?.let{
|
||||
ViewModelProvider(it)[RoadCrossRoamViewModel::class.java]
|
||||
}
|
||||
roadCrossRoamModel?.init(context)
|
||||
automaticExplorationModel = findViewTreeViewModelStoreOwner()?.let{
|
||||
ViewModelProvider(it)[AutomaticExplorationViewModel::class.java]
|
||||
}
|
||||
automaticExplorationModel?.init()
|
||||
ndeViewModel = findViewTreeViewModelStoreOwner()?.let{
|
||||
ViewModelProvider(it)[NDEViewModel::class.java]
|
||||
}
|
||||
ndeViewModel?.init()
|
||||
|
||||
findViewTreeLifecycleOwner()?.lifecycleScope?.launch {
|
||||
viewModel?.messagesFlow?.collect {
|
||||
Log.d(TAG, "${tName()} onMessages update: ${it}")
|
||||
if(it.isNotEmpty()){
|
||||
rv_mind_list.visibility = View.VISIBLE
|
||||
}else{
|
||||
rv_mind_list.visibility = View.VISIBLE
|
||||
}
|
||||
messageAdapter.submitList(it) {
|
||||
Log.d(TAG, "${tName()} adapter submit: ")
|
||||
scrollToBottom()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动到RecyclerView底部
|
||||
private fun scrollToBottom() {
|
||||
val delay = System.currentTimeMillis() - isUserScrollingTime
|
||||
if (delay < SCROLL_THRESHOLD) {
|
||||
return
|
||||
}
|
||||
val layoutManager = rv_mind_list.layoutManager as LinearLayoutManager
|
||||
layoutManager.scrollToPositionWithOffset(messageAdapter.itemCount - 1, 0)
|
||||
}
|
||||
|
||||
fun tName(): String {
|
||||
return "【${Thread.currentThread().name}】"
|
||||
}
|
||||
|
||||
override fun onVisibilityAggregated(isVisible: Boolean) {
|
||||
super.onVisibilityAggregated(isVisible)
|
||||
}
|
||||
|
||||
init {
|
||||
try {
|
||||
initView()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.mogo.eagle.core.data.ai.V2XRepository
|
||||
import com.mogo.eagle.core.data.map.MogoLocation
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
import com.mogo.och.bridge.autopilot.location.OchLocationManager
|
||||
import com.mogo.och.common.module.biz.birdge.BridgeListener
|
||||
import com.mogo.och.common.module.biz.birdge.BridgeManager
|
||||
import com.mogo.och.common.module.voice.VoiceNotice
|
||||
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
|
||||
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MindViewModel : ViewModel(), AIMessageManager.AIMessageListener,
|
||||
BridgeListener {
|
||||
|
||||
private val msgList = mutableListOf<AIMessage>()
|
||||
private var lastTimestamp = System.currentTimeMillis()
|
||||
|
||||
// 记录最后一次事件发生的时间,使用 private set 限制外部修改
|
||||
// private val TIMESTAMP_THRESHOLD = 1000 * 60 * 5 // 5分钟
|
||||
private val TIMESTAMP_THRESHOLD = 1000 * 30
|
||||
|
||||
private var llmResultJob: Job? = null
|
||||
|
||||
private var isChecking = false
|
||||
|
||||
private val _messagesFlow = MutableStateFlow<List<AIMessage>>(emptyList())
|
||||
val messagesFlow: SharedFlow<List<AIMessage>> get() = _messagesFlow
|
||||
|
||||
private val _asrUIStateFlow = MutableStateFlow<AsrUIState>(AsrUIState.Idle)
|
||||
val asrUIStateFlow: StateFlow<AsrUIState> get() = _asrUIStateFlow
|
||||
|
||||
private val tipsTimeOut = "小智还没反应过来,请稍后再试~"
|
||||
private val tipsExit = "我先退下了"
|
||||
val tipsQuestions = listOf(
|
||||
"可以问我:前方路口有拥堵吗?",
|
||||
"可以对我说:介绍一下蘑菇车联?",
|
||||
"想要对话时可以点击:小智智能体",
|
||||
"可以问我:今天天气怎么样?",
|
||||
)
|
||||
private val tipsWakeUpList = listOf(
|
||||
"嗯,我在呢",
|
||||
"在的",
|
||||
"在呢",
|
||||
"你说",
|
||||
)
|
||||
|
||||
private val commontCallback = object : ICommonCallback{
|
||||
override fun showNoTaskView(isTrue: Boolean) {
|
||||
if(isTrue){
|
||||
synchronized(msgList) {
|
||||
msgList.clear()
|
||||
_messagesFlow.value = msgList.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val locationCallback = object : IMoGoChassisLocationGCJ02Listener {
|
||||
override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) {
|
||||
mogoLocation?.let {
|
||||
V2XRepository.provideLocation(it, 0)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
}
|
||||
|
||||
fun setViewCallback(aiView: AiViewCallback) {
|
||||
CommonModel.setRouteLineInfoCallback(TAG,commontCallback)
|
||||
OchLocationManager.addGCJ02Listener(TAG, 1, locationCallback)
|
||||
AIMessageManager.registerListener(this)
|
||||
|
||||
BridgeManager.addBridgeListener(TAG,this)
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun onCleared() {
|
||||
AIMessageManager.unregisterListener(this)
|
||||
llmResultJob?.cancel()
|
||||
CommonModel.setRouteLineInfoCallback(TAG,null)
|
||||
OchLocationManager.removeGCJ02Listener(TAG)
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
override fun onReceive(msg: AIMessage) {
|
||||
Log.d(TAG, "onReceive: $msg")
|
||||
if (isChecking) {
|
||||
if (msg is AIMessage.Event) {
|
||||
msg.showScanFlag = true
|
||||
}
|
||||
}
|
||||
|
||||
// 获更新消息
|
||||
updateMsg(msg)
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
clearMsg()
|
||||
}
|
||||
|
||||
private fun handleMsg(newMessage: AIMessage) {
|
||||
val existingIndex = findMessageIndex(newMessage.id)
|
||||
if (existingIndex != -1) {
|
||||
handleExistingMessage(existingIndex, newMessage)
|
||||
} else {
|
||||
handleNewMessage(newMessage)
|
||||
}
|
||||
}
|
||||
|
||||
private fun findMessageIndex(messageId: String): Int {
|
||||
return msgList.indexOfFirst { it.id == messageId }
|
||||
}
|
||||
|
||||
private fun handleExistingMessage(index: Int, newMessage: AIMessage) {
|
||||
val oldMessage = msgList[index]
|
||||
|
||||
newMessage.showTimestamp = oldMessage.showTimestamp
|
||||
msgList[index] = newMessage
|
||||
|
||||
speakMessageIfNeeded(newMessage, isLastMessage = msgList.last() == newMessage)
|
||||
}
|
||||
|
||||
private fun handleNewMessage(newMessage: AIMessage) {
|
||||
updateTimestampIfNeeded(newMessage)
|
||||
msgList.add(newMessage)
|
||||
speakMessageIfNeeded(newMessage, isLastMessage = true)
|
||||
}
|
||||
|
||||
private fun updateTimestampIfNeeded(newMessage: AIMessage) {
|
||||
val time = newMessage.timestamp - lastTimestamp
|
||||
if (time >= TIMESTAMP_THRESHOLD) {
|
||||
newMessage.showTimestamp = true
|
||||
lastTimestamp = newMessage.timestamp
|
||||
}
|
||||
}
|
||||
|
||||
private fun speakMessageIfNeeded(newMessage: AIMessage, isLastMessage: Boolean) {
|
||||
if (isLastMessage && newMessage.tts.isNotEmpty()) {
|
||||
VoiceNotice.showNotice(newMessage.tts)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "AiViewModel"
|
||||
}
|
||||
|
||||
private fun updateMsg(msg: AIMessage) {
|
||||
synchronized(msgList) {
|
||||
handleMsg(msg)
|
||||
_messagesFlow.value = msgList.toList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteMsg(msgId: String) {
|
||||
synchronized(msgList) {
|
||||
val iterator = msgList.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
if (iterator.next().id == msgId) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
_messagesFlow.value = msgList.toList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearMsg() {
|
||||
synchronized(msgList) {
|
||||
msgList.clear()
|
||||
_messagesFlow.value = msgList.toList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun getQuestionsRandomIndex(): Int {
|
||||
return tipsQuestions.indexOf(tipsQuestions.random())
|
||||
}
|
||||
|
||||
interface AiViewCallback {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AsrUIState {
|
||||
object Idle : AsrUIState()
|
||||
data class Listening(val partialText: String) : AsrUIState()
|
||||
data class Recognized(val finalText: String) : AsrUIState()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import com.mogo.och.shuttle.weaknet.passenger.R
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
|
||||
class AIMessageAdapter : ListAdapter<AIMessage, MessageViewHolder>(MessageDiffCallback()) {
|
||||
|
||||
var onItemClickListener: OnItemClickListener? = null
|
||||
|
||||
override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
|
||||
getItem(position)?.let {
|
||||
holder.bind(it, onItemClickListener)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return when (viewType) {
|
||||
AIMessage.TYPE_PNC_ACTION -> PNCActionViewHolder(inflater.inflate(R.layout.item_ai_pnc_action,parent,false))
|
||||
AIMessage.TYPE_ROAD_V2N -> RoadV2NEventViewHolder(inflater.inflate(R.layout.item_ai_road_v2n_event,parent,false))
|
||||
AIMessage.TYPE_ROAD_CROSS -> RoadCrossRoamViewHolder(inflater.inflate(R.layout.item_ai_road_cross_roam,parent,false))// 全息路口
|
||||
AIMessage.TYPE_AUTOMATIC_EXPLORATION -> AutomaticExplorationViewHolder(inflater.inflate(R.layout.item_ai_automatic_exploration,parent,false))// 探查
|
||||
AIMessage.TYPE_NDE -> NDEViewHolder(inflater.inflate(R.layout.item_ai_nde_event,parent,false))// 车龙
|
||||
else -> throw IllegalArgumentException("Invalid view type")
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (getItem(position)) {
|
||||
is AIMessage.Event -> AIMessage.TYPE_EVENT
|
||||
is AIMessage.Scan -> AIMessage.TYPE_SCAN
|
||||
is AIMessage.Light -> AIMessage.TYPE_LIGHT
|
||||
is AIMessage.Speed -> AIMessage.TYPE_SPEED
|
||||
is AIMessage.Warning -> AIMessage.TYPE_WARNING
|
||||
is AIMessage.PNCAction -> AIMessage.TYPE_PNC_ACTION
|
||||
is AIMessage.RoadV2NEvent -> AIMessage.TYPE_ROAD_V2N
|
||||
is AIMessage.RoadCrossRoam -> AIMessage.TYPE_ROAD_CROSS
|
||||
is AIMessage.AutomaticExploration -> AIMessage.TYPE_AUTOMATIC_EXPLORATION
|
||||
is AIMessage.NDEData -> AIMessage.TYPE_NDE
|
||||
else -> AIMessage.TYPE_EVENT
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: MessageViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
holder.viewRecycled(holder)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.mogo.eagle.core.data.notice.AutoExplorationEntity
|
||||
import com.mogo.eagle.core.data.v2x.RoadV2NEventType
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager
|
||||
import com.mogo.eagle.core.function.hmi.ui.notice.exploration.AutomaticExplorationAdapter
|
||||
import com.mogo.eagle.core.function.hmi.ui.v2n.RoadV2NEventLivePlayView
|
||||
import com.mogo.eagle.core.function.view.MapRoamView
|
||||
import com.mogo.eagle.core.function.view.RoadCrossRoamListAdapter
|
||||
import com.mogo.eagle.core.utilcode.mogo.glide.GlideImageLoader
|
||||
import com.mogo.eagle.core.utilcode.mogo.imageloader.MogoImageView
|
||||
import com.mogo.eagle.core.utilcode.util.DateTimeUtils
|
||||
import com.mogo.och.shuttle.weaknet.passenger.R
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
abstract class MessageViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
abstract fun bind(item: AIMessage, onItemClickListener: OnItemClickListener? = null)
|
||||
open fun viewRecycled(holder: MessageViewHolder){}
|
||||
private val sampleDateFormat = SimpleDateFormat("HH:mm", Locale.CHINA)
|
||||
protected val TAG = javaClass.simpleName
|
||||
|
||||
fun handleTimestamp(item: AIMessage, tvTimestamp: TextView) {
|
||||
if (item.showTimestamp) {
|
||||
tvTimestamp.visibility = View.VISIBLE
|
||||
tvTimestamp.text = sampleDateFormat.format(Date(item.timestamp))
|
||||
} else {
|
||||
tvTimestamp.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
fun View.setVisibilityBasedOn(condition: Boolean) {
|
||||
visibility = if (condition) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
fun TextView.setTextAndVisibility(text: String) {
|
||||
if (text.isEmpty()) {
|
||||
visibility = View.GONE
|
||||
this.text = ""
|
||||
} else {
|
||||
visibility = View.VISIBLE
|
||||
this.text = text
|
||||
}
|
||||
}
|
||||
|
||||
fun ImageView.showOrHideWithUrl(url: String) {
|
||||
if (url.isEmpty()) {
|
||||
visibility = View.GONE
|
||||
|
||||
} else {
|
||||
visibility = View.VISIBLE
|
||||
Glide.with(this)
|
||||
.load(url)
|
||||
.placeholder(R.drawable.icon_pic_holder)
|
||||
.error(R.drawable.icon_pic_error)
|
||||
// .error(R.drawable.icon_marker_window_place_holder)
|
||||
// .placeholder(R.drawable.icon_marker_window_place_holder)
|
||||
.into(this)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PNCActionViewHolder(binding: View) : MessageViewHolder(binding){
|
||||
|
||||
private var tvPncActionDesc: TextView = binding.findViewById(R.id.tvPNCHintContent)
|
||||
|
||||
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
|
||||
if(item is AIMessage.PNCAction){
|
||||
tvPncActionDesc.text = item.actionDesc
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RoadV2NEventViewHolder(binding: View) : MessageViewHolder(binding){
|
||||
|
||||
private var tvV2XHintContent: TextView = binding.findViewById(R.id.tvV2XHintContent)
|
||||
private var containerImageAndLiveVideo: FrameLayout = binding.findViewById(R.id.containerImageAndLiveVideo)
|
||||
private var livePlayView: RoadV2NEventLivePlayView = binding.findViewById(R.id.livePlayView)
|
||||
private var contentImageView: MogoImageView = binding.findViewById(R.id.contentImageView)
|
||||
|
||||
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
|
||||
if(item is AIMessage.RoadV2NEvent){
|
||||
tvV2XHintContent.text = item.title
|
||||
when (item.eventType) {
|
||||
RoadV2NEventType.TEXT -> {
|
||||
containerImageAndLiveVideo.visibility = View.GONE
|
||||
contentImageView.visibility = View.GONE
|
||||
livePlayView.visibility = View.GONE
|
||||
}
|
||||
|
||||
RoadV2NEventType.IMAGE -> {
|
||||
containerImageAndLiveVideo.visibility = View.VISIBLE
|
||||
contentImageView.visibility = View.VISIBLE
|
||||
livePlayView.visibility = View.GONE
|
||||
GlideImageLoader.getInstance()
|
||||
.displayImage(item.contentImageUrl, contentImageView)
|
||||
}
|
||||
|
||||
RoadV2NEventType.LIVE_VIDEO -> {
|
||||
containerImageAndLiveVideo.visibility = View.VISIBLE
|
||||
contentImageView.visibility = View.GONE
|
||||
livePlayView.visibility = View.VISIBLE
|
||||
val cityCode =
|
||||
CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84().cityCode
|
||||
livePlayView.startRoadCameraLive(
|
||||
item.id,
|
||||
item.cameraIp, item.lon, item.lat, cityCode
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RoadCrossRoamViewHolder(binding: View) : MessageViewHolder(binding){
|
||||
|
||||
private var tvRoadRoamTitle: TextView = binding.findViewById(R.id.tvRoadRoamTitle)
|
||||
private var lvRoadCrossRoamTip: RecyclerView = binding.findViewById(R.id.lvRoadCrossRoamTip)
|
||||
|
||||
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
|
||||
if(item is AIMessage.RoadCrossRoam){
|
||||
lvRoadCrossRoamTip.layoutManager = NoScrollLayoutManager(itemView.context)
|
||||
// lvRoadCrossRoamTip.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||
// override fun getItemOffsets(
|
||||
// outRect: Rect,
|
||||
// view: View,
|
||||
// parent: RecyclerView,
|
||||
// state: RecyclerView.State
|
||||
// ) {
|
||||
// super.getItemOffsets(outRect, view, parent, state)
|
||||
// outRect.bottom = 24
|
||||
// }
|
||||
// })
|
||||
lvRoadCrossRoamTip.adapter = RoadCrossRoamListB2Adapter(itemView.context)
|
||||
tvRoadRoamTitle.setTextColor(itemView.context.getColor(R.color.color_131415))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class AutomaticExplorationViewHolder(binding: View) : MessageViewHolder(binding){
|
||||
|
||||
private var rvExplorationList: RecyclerView = binding.findViewById(R.id.rvExplorationList)
|
||||
private lateinit var automaticExplorationAdapter: AutomaticExplorationB2Adapter
|
||||
|
||||
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
|
||||
val linearLayoutManager = LinearLayoutManager(itemView.context)
|
||||
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
|
||||
automaticExplorationAdapter = AutomaticExplorationB2Adapter(itemView.context)
|
||||
rvExplorationList.adapter = automaticExplorationAdapter
|
||||
rvExplorationList.layoutManager = linearLayoutManager
|
||||
initData()
|
||||
}
|
||||
|
||||
private fun initData() {
|
||||
val dataList = ArrayList<AutoExplorationEntity>(7)
|
||||
dataList.add(AutoExplorationEntity("当前道路事件分析",2000L,false))
|
||||
dataList.add(AutoExplorationEntity("前方车辆",2000L,false))
|
||||
dataList.add(AutoExplorationEntity("两侧车辆",2600L,false))
|
||||
dataList.add(AutoExplorationEntity("后方车辆",3000L,false))
|
||||
dataList.add(AutoExplorationEntity("前方路口车辆流速分析",4000L,false))
|
||||
dataList.add(AutoExplorationEntity("前方路口行人/非机动车分析",4300L,false))
|
||||
dataList.add(AutoExplorationEntity("路侧视频分析",5000L,false))
|
||||
automaticExplorationAdapter.setListener(object: AutomaticExplorationB2Adapter.CompleteListener{
|
||||
override fun onComplete(entity: AutoExplorationEntity) {
|
||||
dataList.forEach {
|
||||
if(it.explorationContent == entity.explorationContent){
|
||||
it.explorationComplete = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
automaticExplorationAdapter.setData(dataList)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class NDEViewHolder(binding: View) : MessageViewHolder(binding){
|
||||
|
||||
private var tvNdeContent: TextView = binding.findViewById(R.id.tvNdeHintContent)
|
||||
private var rvNdeList: RecyclerView = binding.findViewById(R.id.rvNdeList)
|
||||
|
||||
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
|
||||
if(item is AIMessage.NDEData){
|
||||
tvNdeContent.text = item.desc
|
||||
val linearLayoutManager = LinearLayoutManager(itemView.context)
|
||||
linearLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
|
||||
val ndeRoadAdapter = AINDERoadAdapter(itemView.context)
|
||||
rvNdeList.adapter = ndeRoadAdapter
|
||||
rvNdeList.layoutManager = linearLayoutManager
|
||||
ndeRoadAdapter.setData(item.roadList)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class NoScrollLayoutManager(context: Context?) : LinearLayoutManager(context) {
|
||||
override fun canScrollVertically(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun canScrollHorizontally(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fun interface OnItemClickListener {
|
||||
fun onItemClick(item: AIMessage, position: Int)
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mogo.och.shuttle.weaknet.passenger.R
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
|
||||
class AINDERoadAdapter(private val context: Context): RecyclerView.Adapter<AINDERoadAdapter.AIRoadHolder>() {
|
||||
|
||||
private var roadList: List<AIMessage.RoadMsg>?= null
|
||||
|
||||
fun setData(list: List<AIMessage.RoadMsg>){
|
||||
roadList = list
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AIRoadHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.b2_item_ai_nde_road, parent, false)
|
||||
return AIRoadHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: AIRoadHolder, position: Int) {
|
||||
roadList?.let{
|
||||
val roadMsg = it[position]
|
||||
if(it.size < 3){
|
||||
//设置item宽度为最大宽度180dp
|
||||
val params = ConstraintLayout.LayoutParams(
|
||||
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 90f,
|
||||
context.resources.displayMetrics).toInt(),
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT)
|
||||
holder.clRoadLayout.layoutParams = params
|
||||
}else if(it.size == 3){
|
||||
//设置item宽度为最大宽度180dp
|
||||
val params = ConstraintLayout.LayoutParams(
|
||||
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60f,
|
||||
context.resources.displayMetrics).toInt(),
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT)
|
||||
holder.clRoadLayout.layoutParams = params
|
||||
}else if(it.size == 4){
|
||||
//设置item宽度为最大宽度180dp
|
||||
val params = ConstraintLayout.LayoutParams(
|
||||
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50f,
|
||||
context.resources.displayMetrics).toInt(),
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT)
|
||||
holder.clRoadLayout.layoutParams = params
|
||||
}else{
|
||||
val params = ConstraintLayout.LayoutParams(
|
||||
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 45f,
|
||||
context.resources.displayMetrics).toInt(),
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT)
|
||||
holder.clRoadLayout.layoutParams = params
|
||||
}
|
||||
when(roadMsg.arrowType){
|
||||
//直行
|
||||
201->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_forward
|
||||
))
|
||||
}
|
||||
//直行或左转
|
||||
202->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_forward_or_turn_left
|
||||
))
|
||||
}
|
||||
//直行或右转
|
||||
203->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_forward_or_turn_right
|
||||
))
|
||||
}
|
||||
//直行或掉头
|
||||
204->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_forward_or_reverse
|
||||
))
|
||||
}
|
||||
//左转
|
||||
205->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_turn_left
|
||||
))
|
||||
}
|
||||
//左转或掉头
|
||||
206->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_turn_left_or_reverse
|
||||
))
|
||||
}
|
||||
//左弯或向左合流
|
||||
207->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_turn_or_merge_left
|
||||
))
|
||||
}
|
||||
//右转
|
||||
208->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_turn_right
|
||||
))
|
||||
}
|
||||
//右转或向右合流
|
||||
209->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_turn_or_merge_right
|
||||
))
|
||||
}
|
||||
//左右转弯
|
||||
210->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_turn_left_or_right
|
||||
))
|
||||
}
|
||||
//掉头
|
||||
211->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_reverse
|
||||
))
|
||||
}
|
||||
//禁止左转
|
||||
212->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_prohibit_turn_left
|
||||
))
|
||||
}
|
||||
//禁止右转
|
||||
213->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_prohibit_turn_right
|
||||
))
|
||||
}
|
||||
//禁止掉头
|
||||
214->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_prohibit_reverse
|
||||
))
|
||||
}
|
||||
//直行或左转或右转
|
||||
215->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_forward_turn_left_right
|
||||
))
|
||||
}
|
||||
//直行或掉头或左转
|
||||
216->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_forward_turn_left_reverse
|
||||
))
|
||||
}
|
||||
//右转或掉头
|
||||
217->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_turn_right_or_reverse
|
||||
))
|
||||
}
|
||||
//禁止右转或向右合流
|
||||
218->{
|
||||
holder.ivRoadType.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_road_prohibit_turn_or_merge_right
|
||||
))
|
||||
}
|
||||
}
|
||||
//是否是推荐车道
|
||||
if(roadMsg.isRecommend){
|
||||
holder.tvRoadStatus.text = context.getString(R.string.nde_road_recommend)
|
||||
holder.tvRoadStatus.setTextColor(context.getColor(R.color.msg_nde_road_recommend))
|
||||
holder.clRoadLayout.background = ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.bg_nde_road_recommend
|
||||
)
|
||||
}
|
||||
//是否有车龙,代表拥堵、行驶缓慢
|
||||
if(roadMsg.isCheLong){
|
||||
holder.tvRoadStatus.text = context.getString(R.string.nde_road_slow)
|
||||
holder.tvRoadStatus.setTextColor(context.getColor(R.color.msg_nde_road_slow))
|
||||
}
|
||||
if(position == it.lastIndex){
|
||||
holder.viewDivider.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = roadList?.size ?: 0
|
||||
|
||||
class AIRoadHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
|
||||
var clRoadLayout: ConstraintLayout = itemView.findViewById(R.id.clRoadLayout)
|
||||
var ivRoadType: ImageView = itemView.findViewById(R.id.ivRoadType)
|
||||
var tvRoadStatus: TextView = itemView.findViewById(R.id.tvRoadStatus)
|
||||
var viewDivider: View = itemView.findViewById(R.id.viewDivider)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.animation.ObjectAnimator
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mogo.eagle.core.data.notice.AutoExplorationEntity
|
||||
import com.mogo.och.shuttle.weaknet.passenger.R
|
||||
|
||||
/**
|
||||
* 自动探查适配器
|
||||
* 鹰眼650需求
|
||||
*/
|
||||
class AutomaticExplorationB2Adapter(val context: Context): RecyclerView.Adapter<AutomaticExplorationB2Adapter.ExplorationHolder>() {
|
||||
|
||||
private var data: List<AutoExplorationEntity> ?= null
|
||||
private var completeListener: CompleteListener ?= null
|
||||
|
||||
fun setData(data: List<AutoExplorationEntity>){
|
||||
this.data = data
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun setListener(listener: CompleteListener){
|
||||
completeListener = listener
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExplorationHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.item_auto_exploration_b2, parent, false)
|
||||
return ExplorationHolder(view)
|
||||
}
|
||||
|
||||
override fun getItemCount() = data?.size ?: 0
|
||||
|
||||
override fun onBindViewHolder(holder: ExplorationHolder, position: Int) {
|
||||
data?.let {
|
||||
val entity = it[position]
|
||||
holder.tvExplorationContent.text = entity.explorationContent
|
||||
holder.ivExplorationLoading.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_exploration_loading_p
|
||||
))
|
||||
val rotationAnim = ObjectAnimator.ofFloat(holder.ivExplorationLoading, "rotation", 0f, 360f)
|
||||
rotationAnim.repeatCount = entity.explorationDuration.toInt()/1000
|
||||
rotationAnim.repeatMode = ValueAnimator.RESTART
|
||||
rotationAnim.duration = 1000
|
||||
rotationAnim.interpolator = LinearInterpolator()
|
||||
rotationAnim.addListener(object: AnimatorListenerAdapter(){
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
super.onAnimationEnd(animation)
|
||||
completeListener?.onComplete(entity)
|
||||
holder.ivExplorationLoading.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_exploration_done_p
|
||||
))
|
||||
}
|
||||
})
|
||||
rotationAnim.start()
|
||||
}
|
||||
}
|
||||
|
||||
class ExplorationHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
|
||||
var ivExplorationLoading: ImageView = itemView.findViewById(R.id.ivExplorationLoading)
|
||||
var tvExplorationContent: TextView = itemView.findViewById(R.id.tvExplorationContent)
|
||||
}
|
||||
|
||||
interface CompleteListener{
|
||||
fun onComplete(entity: AutoExplorationEntity)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
|
||||
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
|
||||
class MessageDiffCallback: DiffUtil.ItemCallback<AIMessage>() {
|
||||
|
||||
override fun areContentsTheSame(oldItem: AIMessage, newItem: AIMessage): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: AIMessage, newItem: AIMessage): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||
import com.mogo.commons.AbsMogoApplication
|
||||
import com.mogo.och.common.module.utils.ResourcesUtils
|
||||
import com.mogo.och.shuttle.weaknet.passenger.R
|
||||
import me.jessyan.autosize.utils.AutoSizeUtils
|
||||
|
||||
class PaddingItemDecoration(private val topPadding: Int, private val bottomPadding: Int) : RecyclerView.ItemDecoration() {
|
||||
|
||||
private var divider: Drawable
|
||||
|
||||
private var padding = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),13f)
|
||||
|
||||
init {
|
||||
val shapeDrawable = GradientDrawable()
|
||||
shapeDrawable.setColor(ResourcesUtils.getColor(R.color.b2_BBC9D4))
|
||||
shapeDrawable.shape = GradientDrawable.RECTANGLE
|
||||
val width = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),343f)
|
||||
val height = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),1f)
|
||||
shapeDrawable.setSize(width, height)
|
||||
divider = shapeDrawable
|
||||
}
|
||||
|
||||
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
|
||||
super.getItemOffsets(outRect, view, parent, state)
|
||||
|
||||
|
||||
// 只有第一个 item 的顶部添加空白
|
||||
if (parent.getChildAdapterPosition(view) == 0) {
|
||||
outRect.top = topPadding
|
||||
} else{
|
||||
outRect.top = 0
|
||||
}
|
||||
|
||||
// 最后一个 item 的底部添加空白
|
||||
// if (parent.getChildAdapterPosition(view) == state.itemCount - 1) {
|
||||
// outRect.bottom = bottomPadding
|
||||
// } else{
|
||||
// outRect.bottom = 0
|
||||
// }
|
||||
}
|
||||
|
||||
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
|
||||
super.onDraw(c, parent, state)
|
||||
val childCount = parent.childCount //获取可见item的数量
|
||||
val spanCount: Int = getSpanCount(parent)
|
||||
for (i in 0 until childCount) {
|
||||
val child = parent.getChildAt(i)
|
||||
val params = child
|
||||
.layoutParams as RecyclerView.LayoutParams
|
||||
val left = child.left - params.leftMargin + padding
|
||||
val right = child.right - padding //- params.rightMargin - divider.intrinsicWidth
|
||||
val top = child.bottom + params.bottomMargin
|
||||
val bottom = top + divider.intrinsicHeight
|
||||
divider.setBounds(left, top, right, bottom)
|
||||
divider.draw(c)
|
||||
if (i < spanCount) { //画第一行顶部的分割线
|
||||
drawHorizontalForFirstRow(c, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawHorizontalForFirstRow(c: Canvas, child: View) {
|
||||
val params = child
|
||||
.layoutParams as RecyclerView.LayoutParams
|
||||
val left = child.left - params.leftMargin - divider.intrinsicWidth
|
||||
val top = child.top - params.topMargin - divider.intrinsicHeight
|
||||
val right = child.right + params.rightMargin + divider.intrinsicWidth
|
||||
val bottom = top + divider.intrinsicHeight
|
||||
divider.setBounds(left, top, right, bottom)
|
||||
divider.draw(c)
|
||||
}
|
||||
|
||||
private fun getSpanCount(parent: RecyclerView): Int {
|
||||
// 列数
|
||||
var spanCount = -1
|
||||
val layoutManager = parent.layoutManager
|
||||
if (layoutManager is GridLayoutManager) {
|
||||
spanCount = layoutManager.spanCount
|
||||
} else if (layoutManager is StaggeredGridLayoutManager) {
|
||||
spanCount = layoutManager
|
||||
.spanCount
|
||||
}
|
||||
return spanCount
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mogo.och.shuttle.weaknet.passenger.R
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
class RoadCrossRoamListB2Adapter(private val mContext: Context) : RecyclerView.Adapter<RoadCrossRoamListB2Adapter.ViewHolder>() {
|
||||
|
||||
private val items: MutableList<String> = mutableListOf()
|
||||
|
||||
init {
|
||||
items.add("前方路况拥堵分析")
|
||||
items.add("路口危险车辆分析")
|
||||
items.add("路口交通事故分析")
|
||||
items.add("路口行人碰撞分析")
|
||||
items.add("路口非机动车分析")
|
||||
items.add("路口灯态分析")
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view: View =
|
||||
LayoutInflater.from(mContext).inflate(R.layout.item_road_cross_ai_roam_tip_b2, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return 6
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
holder.textView.setTextColor(mContext.getColor(R.color.color_191A1C))
|
||||
holder.textView.text = item
|
||||
// 随机决定是否显示ProgressBar
|
||||
// if (Random.nextBoolean()) { // 50%的几率显示ProgressBar
|
||||
holder.progressBar.visibility = View.VISIBLE
|
||||
holder.checkIcon.visibility = View.INVISIBLE
|
||||
|
||||
val r0 = Random.nextInt(0,3)
|
||||
val r1 = Random.nextInt(1,9)
|
||||
// 模拟加载完成
|
||||
holder.itemView.postDelayed({
|
||||
holder.progressBar.visibility = View.INVISIBLE
|
||||
holder.checkIcon.visibility = View.VISIBLE
|
||||
},r0 * 1000L + r1 * 100L)
|
||||
// } else {
|
||||
// holder.progressBar.visibility = View.GONE
|
||||
// holder.checkIcon.visibility = View.VISIBLE
|
||||
// }
|
||||
}
|
||||
|
||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
var textView: TextView = itemView.findViewById(R.id.tvRoadItemTip)
|
||||
var progressBar: ProgressBar = itemView.findViewById(R.id.pbRoadItemTip)
|
||||
var checkIcon: ImageView = itemView.findViewById(R.id.ivRoadItemTip)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean
|
||||
|
||||
import android.os.CountDownTimer
|
||||
import android.util.Log
|
||||
import com.mogo.eagle.core.data.v2x.RoadV2NEventType
|
||||
import kotlin.math.floor
|
||||
|
||||
|
||||
sealed class AIMessage(
|
||||
open val id: String,
|
||||
open val title: String,
|
||||
open val tts: String = "",
|
||||
val timestamp: Long = System.currentTimeMillis(),
|
||||
var showTimestamp: Boolean = false
|
||||
) {
|
||||
|
||||
companion object {
|
||||
const val TYPE_SCAN = 0
|
||||
const val TYPE_EVENT = 1
|
||||
const val TYPE_LIGHT = 3
|
||||
const val TYPE_SPEED = 4
|
||||
const val TYPE_WARNING = 5
|
||||
const val TYPE_PNC_ACTION = 6
|
||||
const val TYPE_ROAD_V2N = 7
|
||||
const val TYPE_ROAD_CROSS = 8
|
||||
const val TYPE_AUTOMATIC_EXPLORATION = 9
|
||||
const val TYPE_NDE = 11
|
||||
}
|
||||
|
||||
data class Scan(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
val pictureUrl: String = "",
|
||||
var showScanFlag: Boolean = false
|
||||
) : AIMessage(id, title)
|
||||
|
||||
data class Event(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val tts: String = "",
|
||||
val position: String = "",
|
||||
val distance: String = "",
|
||||
val range: String = "",
|
||||
val time: String = "",
|
||||
val pictureUrl: String = "",
|
||||
val videoUrl: String = "",
|
||||
var showScanFlag: Boolean = false
|
||||
) : AIMessage(id, title, tts)
|
||||
|
||||
data class QA(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val tts: String = "",
|
||||
val question: String,
|
||||
val answer: String,
|
||||
var state: QuestionState = QuestionState.UNDERSTAND,
|
||||
val pictureUrl: String = "",
|
||||
var pictureUrlList: List<String> = listOf(),
|
||||
val videoUrl: String = "",
|
||||
) : AIMessage(id, title, tts) {
|
||||
|
||||
enum class QuestionState(val code: Int) {
|
||||
UNDERSTAND(1),
|
||||
ANALYZE(2),
|
||||
ANSWER(3),
|
||||
FINISH(4),
|
||||
ERROR(-1),
|
||||
}
|
||||
}
|
||||
|
||||
data class Light(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val tts: String = "",
|
||||
var seconds: Int,
|
||||
val status: Int
|
||||
) : AIMessage(id, title, tts) {
|
||||
private var countDownTimer: CountDownTimer? = null
|
||||
private var listener: OnCountdownUpdateListener? = null
|
||||
|
||||
fun startCountdown(millisInFuture: Long, countDownInternal: Long) {
|
||||
countDownTimer?.cancel()
|
||||
countDownTimer = object : CountDownTimer(millisInFuture, countDownInternal) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
//倒计时开始
|
||||
Log.d(
|
||||
"StartOrSlowDownTip",
|
||||
"millisUntilFinished = $millisUntilFinished, countDownInternal = $countDownInternal"
|
||||
)
|
||||
val cd = millisUntilFinished / 1000.0
|
||||
// val split = String.format("%.2f", cd).split(".")
|
||||
seconds = floor(cd).toInt()
|
||||
listener?.onCountdownUpdate()
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
//倒计时完成
|
||||
seconds = 0
|
||||
listener?.onCountdownFinish()
|
||||
}
|
||||
}
|
||||
countDownTimer?.start()
|
||||
}
|
||||
|
||||
fun stopCountdown() {
|
||||
countDownTimer?.cancel()
|
||||
}
|
||||
|
||||
fun setOnCountdownUpdateListener(listener: OnCountdownUpdateListener) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
interface OnCountdownUpdateListener {
|
||||
fun onCountdownUpdate()
|
||||
fun onCountdownFinish()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data class Speed(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val tts: String = "",
|
||||
val speedMax: Int,
|
||||
val speedMin: Int,
|
||||
) : AIMessage(id, title, tts)
|
||||
|
||||
data class Warning(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val tts: String = "",
|
||||
) : AIMessage(id, title, tts)
|
||||
|
||||
data class PNCAction(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
var actionDesc: String,
|
||||
var timeStamp: Long = 0, //事件发生事件戳
|
||||
): AIMessage(id,title)
|
||||
|
||||
data class RoadV2NEvent(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val tts: String = "", //TTS的文案
|
||||
var eventType: RoadV2NEventType, //事件弹框类型
|
||||
var timeStamp: Long = 0, //事件发生事件戳
|
||||
var iconResId: Int, //事件icon res id
|
||||
var isNeedTTS: Boolean = false, //事件文案是否需要同步tts
|
||||
var contentImageUrl: String, // Image 类型时图片 url
|
||||
var cameraIp: String, // 路侧camera ip,用于请求获取拉流地址
|
||||
var lon: Double, //事件坐标-经度
|
||||
var lat: Double, //事件坐标-纬度
|
||||
): AIMessage(id,title,tts)
|
||||
|
||||
data class RoadCrossRoam(
|
||||
override val id: String,
|
||||
override val title: String
|
||||
): AIMessage(id,title)
|
||||
|
||||
data class AutomaticExploration(
|
||||
override val id: String,
|
||||
override val title: String
|
||||
): AIMessage(id,title)
|
||||
|
||||
data class EvaluateData(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
var isFirst:Boolean = true
|
||||
): AIMessage(id,title)
|
||||
|
||||
data class NDEData(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
var desc: String,
|
||||
var roadList: List<RoadMsg>
|
||||
): AIMessage(id,title)
|
||||
|
||||
data class RoadMsg(
|
||||
var arrowType: Int, // 车道类型,如直行201(详情参考文件:message_pad.proto)
|
||||
var laneNum: Int,// 车道号
|
||||
var isRecommend: Boolean,// 是否是推荐车道
|
||||
var isCheLong: Boolean// 是否有车龙,代表拥堵、行驶缓慢
|
||||
)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean
|
||||
|
||||
data class ListenUIState(val show: Boolean, val text: String, val showTips: Boolean = false)
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
|
||||
|
||||
import android.os.CountDownTimer
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
|
||||
import com.mogo.eagle.core.data.msgbox.MsgBoxType
|
||||
import com.mogo.eagle.core.data.msgbox.MsgCategory
|
||||
import com.mogo.eagle.core.function.api.datacenter.msgbox.IMsgBoxListener
|
||||
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxListenerManager
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
|
||||
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
|
||||
/**
|
||||
* 自动探查
|
||||
*/
|
||||
class AutomaticExplorationViewModel: ViewModel(), IMsgBoxListener, ICommonCallback {
|
||||
|
||||
companion object{
|
||||
private const val TAG = "AutomaticExplorationViewModel"
|
||||
private const val EXPLORATION_SHOW_TIME = 300000L //距离用户在触发上一次事件播报的时间5分钟后,自动触发常规道路情况检测
|
||||
}
|
||||
|
||||
private var showViewTimer: CountDownTimer?= null //展示自动探查倒计时
|
||||
private var isCountingDown: Boolean = false //是否处于倒计时中
|
||||
private var hasOrder: Boolean = false // 车当前是否有订单
|
||||
|
||||
fun init(){
|
||||
CommonModel.setRouteLineInfoCallback(TAG,this)
|
||||
CallerMsgBoxListenerManager.addListener(TAG,this)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
CommonModel.setRouteLineInfoCallback(TAG,null)
|
||||
CallerMsgBoxListenerManager.removeListener(TAG)
|
||||
}
|
||||
|
||||
override fun showNoTaskView(isTrue: Boolean) {
|
||||
super.showNoTaskView(isTrue)
|
||||
if(isTrue){
|
||||
cancelTimer()
|
||||
currentOrderStatus(false)
|
||||
}else{
|
||||
startShowTimer()
|
||||
currentOrderStatus(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onDataChanged(category: MsgCategory, msgBoxList: MsgBoxBean) {
|
||||
if(category == MsgCategory.NOTICE){
|
||||
if(msgBoxList.type == MsgBoxType.V2X){
|
||||
//重置倒计时时长
|
||||
cancelTimer()
|
||||
if(hasOrder){
|
||||
startShowTimer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消倒计时
|
||||
*/
|
||||
private fun cancelTimer(){
|
||||
CallerLogger.d(TAG,"cancelTimer")
|
||||
showViewTimer?.cancel()
|
||||
showViewTimer = null
|
||||
isCountingDown = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始倒计时
|
||||
*/
|
||||
private fun startShowTimer(){
|
||||
CallerLogger.d(TAG,"startShowTimer")
|
||||
if(!isCountingDown){
|
||||
ThreadUtils.runOnUiThread {
|
||||
if(showViewTimer == null){
|
||||
showViewTimer = object: CountDownTimer(EXPLORATION_SHOW_TIME,EXPLORATION_SHOW_TIME){
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
CallerLogger.d(TAG,"倒计时+:${millisUntilFinished}")
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
if(hasOrder){
|
||||
showAutoExploration()
|
||||
}
|
||||
isCountingDown = false
|
||||
}
|
||||
}
|
||||
}
|
||||
isCountingDown = true
|
||||
showViewTimer?.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前订单状态
|
||||
* @param orderStatus true有订单;false没有订单
|
||||
*/
|
||||
private fun currentOrderStatus(orderStatus: Boolean){
|
||||
hasOrder = orderStatus
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun showAutoExploration(){
|
||||
val automaticExploration = AIMessage.AutomaticExploration(System.currentTimeMillis().toString(),"")
|
||||
AIMessageManager.post(automaticExploration)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
import mogo.telematics.pad.MessagePad.TrackedObject
|
||||
|
||||
/**
|
||||
* 车龙信息
|
||||
*/
|
||||
class NDEViewModel: ViewModel(), IMoGoAutopilotIdentifyListener {
|
||||
|
||||
companion object{
|
||||
private const val TAG = "NDEViewModel"
|
||||
}
|
||||
|
||||
private var lastMap2 = HashMap<Int, String>()
|
||||
private var lastTime = 0L
|
||||
|
||||
fun init(){
|
||||
CallerAutopilotIdentifyListenerManager.addListener(TAG, this)
|
||||
}
|
||||
|
||||
override fun onAutopilotIdentifyDataUpdate(trafficData: List<TrackedObject>?){
|
||||
super.onAutopilotIdentifyDataUpdate(trafficData)
|
||||
handleCheLong(trafficData)
|
||||
}
|
||||
|
||||
private fun handleCheLong(trafficData: List<TrackedObject>?) {
|
||||
var hasCheLong = false
|
||||
var isNewData = false
|
||||
val roadMsgList = ArrayList<AIMessage.RoadMsg>()
|
||||
val curMap = HashMap<Int, String>()
|
||||
if (lastTime > 0 && System.currentTimeMillis() - lastTime > 60000) {
|
||||
lastMap2.clear()// 清除上次车龙事件的缓存
|
||||
}
|
||||
var lastLocStr: String? = ""
|
||||
trafficData?.forEach { obj ->
|
||||
if (obj.type == 707) {// 当前方向所有车道
|
||||
if (obj.polygonCount > 1) {// 当次数据有车龙事件
|
||||
lastLocStr = lastMap2[obj.laneNum]
|
||||
// 1. 上次无车龙但此次有车龙,认为是新车龙事件
|
||||
// 2. 两次都有车龙,则判断车龙的长度是否相同
|
||||
if (lastLocStr == null || lastLocStr == "0" || lastLocStr != "${obj.polygonList[0]}-${obj.polygonList[obj.polygonCount - 1]}") {
|
||||
isNewData = true
|
||||
}
|
||||
hasCheLong = true
|
||||
|
||||
// key: 车道号,value: 非0代表有车龙且首、尾两个点可计算车龙长度
|
||||
curMap[obj.laneNum] =
|
||||
"${obj.polygonList[0]}-${obj.polygonList[obj.polygonCount - 1]}"
|
||||
} else {// 当次没有车龙
|
||||
if (lastMap2[obj.laneNum] != null && lastMap2[obj.laneNum] != "0") {// 3. 上次有车龙,这次无车龙
|
||||
isNewData = true
|
||||
}
|
||||
// key: 车道号,value: 0代表无车龙
|
||||
curMap[obj.laneNum] = "0"
|
||||
}
|
||||
// 保存所有车道信息
|
||||
roadMsgList.add(
|
||||
AIMessage.RoadMsg(
|
||||
obj.arrowType,
|
||||
laneNum = obj.laneNum,
|
||||
isRecommend = obj.suggestedLanes,
|
||||
isCheLong = obj.polygonCount > 1
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (isNewData) {
|
||||
// 清除上次车道信息
|
||||
lastMap2.clear()
|
||||
if (hasCheLong) {
|
||||
// 缓存当次车龙事件所有车道信息
|
||||
lastMap2.putAll(curMap)
|
||||
lastTime = System.currentTimeMillis()
|
||||
|
||||
val sortedList = roadMsgList.sortedWith(compareByDescending { it.laneNum })
|
||||
val ndeEvent = AIMessage.NDEData(System.currentTimeMillis().toString(),"路口车龙","前方路口有车龙",sortedList)
|
||||
AIMessageManager.post(ndeEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.mogo.eagle.core.data.autopilot.pnc.PncActionsHelper
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotPlanningActionsListener
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningActionsListenerManager
|
||||
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
|
||||
import com.mogo.och.common.module.manager.loop.BizLoopManager
|
||||
import com.mogo.och.data.bean.BusStationBean
|
||||
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
|
||||
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
import mogo.telematics.pad.MessagePad
|
||||
|
||||
class PNCActionsViewModel: ViewModel(), IMoGoAutopilotPlanningActionsListener, ICommonCallback {
|
||||
|
||||
companion object{
|
||||
private const val TAG = "PNCActionsViewModel"
|
||||
}
|
||||
|
||||
private var currentAction = ""
|
||||
|
||||
private var currentStation:BusStationBean?=null
|
||||
|
||||
fun init(){
|
||||
CallerPlanningActionsListenerManager.addListener(TAG, this)
|
||||
CommonModel.setRouteLineInfoCallback(TAG,this)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
CallerPlanningActionsListenerManager.removeListener(TAG)
|
||||
CommonModel.setRouteLineInfoCallback(TAG,null)
|
||||
}
|
||||
|
||||
override fun updateStationsInfo(
|
||||
stations: MutableList<BusStationBean>?,
|
||||
currentStationIndex: Int,
|
||||
isArrived: Boolean
|
||||
) {
|
||||
try {
|
||||
currentStation = stations?.get(currentStationIndex)
|
||||
}catch (e:Exception){
|
||||
OchChainLogManager.writeChainLogError("PNCActionsViewModel 设置错误","${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun showNoTaskView(isTrue: Boolean) {
|
||||
super.showNoTaskView(isTrue)
|
||||
if(isTrue){
|
||||
currentStation = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun pncActions(planningActionMsg: MessagePad.PlanningActionMsg) {
|
||||
try {
|
||||
BizLoopManager.runInMainThread {
|
||||
if (CallerAutoPilotStatusListenerManager.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
|
||||
var actions: String? = null
|
||||
planningActionMsg.actionMsg?.let {
|
||||
try {
|
||||
actions = PncActionsHelper.getAction(
|
||||
it.drivingState.number,
|
||||
it.drivingAction.number
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
planningActionMsg.v2NActionMsgList?.forEach { v2nAction ->
|
||||
actions = PncActionsHelper.getAction(
|
||||
v2nAction.drivingState.number,
|
||||
v2nAction.drivingAction.number
|
||||
)
|
||||
}
|
||||
// update view
|
||||
actions?.let {
|
||||
if(it.isNotEmpty() && it != currentAction){
|
||||
currentAction = it
|
||||
val title = getActionTitle(it)
|
||||
if(title.isNotEmpty()){
|
||||
val desc = getActionDesc(title)
|
||||
val action = AIMessage.PNCAction(it+System.currentTimeMillis(),title,desc,System.currentTimeMillis())
|
||||
AIMessageManager.post(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getActionTitle(pncAction: String): String{
|
||||
return when(pncAction){
|
||||
"正在进站"->{
|
||||
"车辆进站"
|
||||
}
|
||||
"等待进站"->{
|
||||
"车辆等待进站"
|
||||
}
|
||||
"正在出站"->{
|
||||
"车辆出站"
|
||||
}
|
||||
"等待出站"->{
|
||||
"车辆等待出站"
|
||||
}
|
||||
"正在向左变道"->{
|
||||
"车辆向左变道"
|
||||
}
|
||||
"正在向右变道"->{
|
||||
"车辆向右变道"
|
||||
}
|
||||
"正在完成变道"->{
|
||||
"车辆完成变道"
|
||||
}
|
||||
"正在绕过障碍物"->{
|
||||
"车辆正在绕过前方障碍物"
|
||||
}
|
||||
"正在向左绕行避让前方静止障碍物"->{
|
||||
"车辆正在绕过前方障碍物"
|
||||
}
|
||||
"正在向右绕行避让前方静止障碍物"->{
|
||||
"车辆正在绕过前方障碍物"
|
||||
}
|
||||
"正在避让障碍物"->{
|
||||
"车辆正在避让前方障碍物"
|
||||
}
|
||||
"正在向左变道避让前方静止障碍物"->{
|
||||
"车辆正在避让前方障碍物"
|
||||
}
|
||||
"正在向右变道避让前方静止障碍物"->{
|
||||
"车辆正在避让前方障碍物"
|
||||
}
|
||||
"正在等红灯"->{
|
||||
"路口等红灯"
|
||||
}
|
||||
"正在向左变道避让前方道路施工"->{
|
||||
"车辆正在变道避让前方道路施工"
|
||||
}
|
||||
"正在向右变道避让前方道路施工"->{
|
||||
"车辆正在变道避让前方道路施工"
|
||||
}
|
||||
"正在向左绕行避让前方道路施工"->{
|
||||
"车辆正在绕行避让前方道路施工"
|
||||
}
|
||||
"正在向右绕行避让前方道路施工"->{
|
||||
"车辆正在绕行避让前方道路施工"
|
||||
}
|
||||
|
||||
"正在向左变道避让前方道路事故"->{
|
||||
"车辆正在变道避让前方道路事故"
|
||||
}
|
||||
"正在向右变道避让前方道路事故"->{
|
||||
"车辆正在变道避让前方道路事故"
|
||||
}
|
||||
"正在向左绕行避让前方道路事故"->{
|
||||
"车辆正在绕行避让前方道路事故"
|
||||
}
|
||||
"正在向右绕行避让前方道路事故"->{
|
||||
"车辆正在绕行避让前方道路事故"
|
||||
}
|
||||
"正在跟随车辆行驶"->{
|
||||
"车辆正在跟车通行"
|
||||
}
|
||||
"正在跟车行驶"->{
|
||||
"车辆正在跟车通行"
|
||||
}
|
||||
"正在向左变道避让前方车龙"->{
|
||||
"车辆正在绕行前方车龙"
|
||||
}
|
||||
"正在向右变道避让前方车龙"->{
|
||||
"车辆正在绕行前方车龙"
|
||||
}
|
||||
"正在使用云端规划通过路口"->{
|
||||
"车辆正在使用云端轨迹通行"
|
||||
}
|
||||
"正在避让后方来车"->{
|
||||
"车辆正在避让后方来车"
|
||||
}
|
||||
else->{
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getActionDesc(action: String): String{
|
||||
return when(action){
|
||||
"车辆进站"->{
|
||||
"前方即将到达${CommonModel.routesResult}," +
|
||||
"车辆正在规划减速并进站停靠,请安心等待车辆停稳再下车哦~"
|
||||
}
|
||||
"车辆等待进站"->{
|
||||
"车辆待环境安全后进站,耐心等几秒,安全比赶路更重要~"
|
||||
}
|
||||
"车辆出站"->{
|
||||
"欢迎乘坐MOGO RoboTaxi~车辆正在规划出站,坐稳扶好哦,我们出发啦!小智持续守护您的行程。"
|
||||
}
|
||||
"车辆等待出站"->{
|
||||
"车辆待环境安全后出站,耐心等几秒,安全比赶路更重要~"
|
||||
}
|
||||
"车辆向左变道"->{
|
||||
"确认环境安全,车辆正在规划平稳向左变道,同时持续监测周边交通参与者动向,放心交给我们吧!"
|
||||
}
|
||||
"车辆向右变道"->{
|
||||
"确认环境安全,车辆正在规划平稳向右变道,同时持续监测周边交通参与者动向,放心交给我们吧!"
|
||||
}
|
||||
"车辆完成变道"->{
|
||||
"变道完成啦,继续前进!小智持续守护您的行程。"
|
||||
}
|
||||
"车辆正在绕过前方障碍物"->{
|
||||
"发现前方障碍物,车辆正在规划平稳变道,即将画出一条完美弧线~"
|
||||
}
|
||||
"车辆正在避让前方障碍物"->{
|
||||
"发现前方障碍物,车辆正在规划平稳避让,诠释优雅与丝滑~"
|
||||
}
|
||||
"车辆完成绕障"->{
|
||||
"绕障完成啦,继续前进!小智持续守护您的行程。"
|
||||
}
|
||||
"路口等红灯"->{
|
||||
"车辆正在路口等红灯,可以安心放空望望窗外~小智一直在您身边哦!"
|
||||
}
|
||||
"车辆正在变道避让前方道路施工"->{
|
||||
"车辆正在提前规划变道避让前方道路施工,稳稳的很安心~您已体验到车路云一体化协同应用场景,是当之无愧的先锋体验官!"
|
||||
}
|
||||
"车辆正在绕行避让前方道路施工"->{
|
||||
"车辆正在提前规划绕行避让前方道路施工,稳稳的很安心~您已体验到车路云一体化协同应用场景,是当之无愧的先锋体验官!"
|
||||
}
|
||||
"车辆正在变道避让前方道路事故"->{
|
||||
"车辆正在提前规划变道避让前方道路事故,放心看我表现吧!您已体验到车路云一体化协同应用场景,小智为您欢呼!"
|
||||
}
|
||||
"车辆正在绕行避让前方道路事故"->{
|
||||
"车辆正在提前规划绕行避让前方道路事故,放心看我表现吧!您已体验到车路云一体化协同应用场景,小智为您欢呼!"
|
||||
}
|
||||
"车辆正在跟车通行"->{
|
||||
"车辆正在跟随前车通行,舒适度MAX~您已体验到车路云一体化协同应用场景,超越全国99%的乘客!"
|
||||
}
|
||||
"车辆正在绕行前方车龙"->{
|
||||
"车辆正在提前规划变道避让路口车龙,舒适度MAX~。您已体验到车路云一体化协同应用场景,超越全国99%的乘客!"
|
||||
}
|
||||
"车辆正在使用云端轨迹通行"->{
|
||||
"前方智慧路口内有障碍物,车辆正在使用云端规划轨迹通行。您已体验到车路云一体化协同应用场景,超越全国99%的乘客!"
|
||||
}
|
||||
"车辆正在避让后方来车"->{
|
||||
"车辆正在避让后方来车,耐心等几秒,安全比赶路更重要~"
|
||||
}
|
||||
else->{
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.mogo.commons.voice.AIAssist
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.function.api.map.road.IMoGoMapRoadListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerServicesEventManager
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapIdentifyManager
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
|
||||
class RoadCrossRoamViewModel: ViewModel(), IMoGoMapRoadListener {
|
||||
|
||||
companion object{
|
||||
const val TAG = "RoadCrossRoamViewModel"
|
||||
}
|
||||
|
||||
private lateinit var mContext: Context
|
||||
|
||||
fun init(context: Context){
|
||||
CallerMapRoadListenerManager.addListener(TAG, this)
|
||||
mContext = context
|
||||
}
|
||||
|
||||
override fun onCrossDevice(trigger: Boolean) {
|
||||
super.onCrossDevice(trigger)
|
||||
if(trigger){
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun show(){
|
||||
// 没有路线不做提示
|
||||
if (CallerAutoPilotStatusListenerManager.getLineId() == 0L) {
|
||||
CallerLogger.d(TAG, "没有路线不做提示")
|
||||
return
|
||||
}
|
||||
// 处于漫游模式下不做处理
|
||||
if (CallerMapIdentifyManager.roam.second) {
|
||||
if (CallerMapIdentifyManager.roam.first != TAG) {
|
||||
ToastUtils.showLong("正在漫游中,不展示路口漫游")
|
||||
}
|
||||
CallerLogger.d(TAG, "正在漫游中,不展示路口漫游")
|
||||
return
|
||||
}
|
||||
// 首页被遮挡不做提示
|
||||
if (!CallerHmiViewControlListenerManager.getMainPageVisible()) {
|
||||
CallerLogger.d(TAG, "attachView return , mainPageVisible is false")
|
||||
return
|
||||
}
|
||||
// 没有路侧设备,不做处理
|
||||
CallerLogger.d(TAG, "命中,attachView")
|
||||
val cross = CallerMapRoadListenerManager.getCrossEndInfo()
|
||||
if (cross.isNullOrEmpty()) {
|
||||
CallerLogger.d(TAG, "未触发,路口ID:$cross")
|
||||
return
|
||||
}
|
||||
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)){
|
||||
val disStr = "为您提供路口全息影像,助力出行"
|
||||
AIAssist.getInstance(mContext).speakTTSVoiceWithLevel(disStr, AIAssist.NEW_LEVEL_2)
|
||||
}
|
||||
CallerServicesEventManager.updateServicesNum(CallerServicesEventManager.ServiceType.ROAD)
|
||||
AIMessageManager.post(AIMessage.RoadCrossRoam(System.currentTimeMillis().toString(),""))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
|
||||
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.mogo.commons.utils.MogoAnalyticUtils
|
||||
import com.mogo.eagle.core.data.v2x.RoadV2NEventWindowBean
|
||||
import com.mogo.eagle.core.function.api.hmi.v2n.IRoadV2NEventWindowListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerRoadV2NEventWindowListenerManager
|
||||
import com.mogo.eagle.core.function.hmi.ui.utils.HmiActionLog
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
|
||||
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class RoadV2NEventViewModel: ViewModel(), IRoadV2NEventWindowListener {
|
||||
|
||||
companion object{
|
||||
const val TAG = "RoadV2NEventViewModel"
|
||||
const val ANALYTICS_KEY = "hmi_road_event_window_view"
|
||||
|
||||
fun trackEvent(msg: String) {
|
||||
ProcessLifecycleOwner.get().lifecycleScope.launch(Dispatchers.IO) {
|
||||
val map: MutableMap<String, Any> = HashMap()
|
||||
map["msg"] = msg
|
||||
MogoAnalyticUtils.track(
|
||||
ANALYTICS_KEY,
|
||||
map
|
||||
)
|
||||
HmiActionLog.hmiAction(TAG, msg)
|
||||
}
|
||||
CallerLogger.i(TAG, msg)
|
||||
}
|
||||
}
|
||||
|
||||
fun init(){
|
||||
CallerRoadV2NEventWindowListenerManager.addListener(TAG, this)
|
||||
}
|
||||
|
||||
override fun show(dataBean: RoadV2NEventWindowBean) {
|
||||
trackEvent("show --> $dataBean")
|
||||
val canShowV2NEventWindowView = CallerHmiViewControlListenerManager.getMainPageVisible()
|
||||
if (!canShowV2NEventWindowView) {
|
||||
trackEvent("show --> 当前不在高精地图页面,跳过")
|
||||
return
|
||||
}
|
||||
val lineId = CallerAutoPilotStatusListenerManager.getLineId()
|
||||
if (lineId <= 0) {
|
||||
trackEvent("show --> 当前无订单,跳过")
|
||||
return
|
||||
}
|
||||
val event = AIMessage.RoadV2NEvent(
|
||||
dataBean.eventId,
|
||||
dataBean.hintStr,
|
||||
"",
|
||||
dataBean.eventType,
|
||||
dataBean.timestamp,
|
||||
dataBean.iconResId,
|
||||
false,
|
||||
dataBean.contentImageUrl,
|
||||
dataBean.cameraIp,
|
||||
dataBean.lon,
|
||||
dataBean.lat
|
||||
)
|
||||
AIMessageManager.post(event)
|
||||
}
|
||||
|
||||
override fun dismiss(eventId: String) {
|
||||
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 791 B |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient android:startColor="@color/b2_D7F1FF" android:endColor="@color/common_color_00000000" android:angle="-90"/>
|
||||
<corners android:radius="@dimen/dp_18"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#DDDDDD" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<inset android:inset="100dp">
|
||||
<bitmap android:src="@drawable/icon_image_error" />
|
||||
</inset>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#DDDDDD" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<inset android:inset="100dp">
|
||||
<bitmap android:src="@drawable/icon_image_holder" />
|
||||
</inset>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/clRoadLayout"
|
||||
android:layout_width="@dimen/dp_90"
|
||||
android:layout_height="@dimen/dp_120"
|
||||
android:minWidth="@dimen/dp_90"
|
||||
android:maxWidth="@dimen/dp_180"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivRoadType"
|
||||
android:layout_width="@dimen/dp_55"
|
||||
android:layout_height="@dimen/dp_55"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:contentDescription="@string/nde_road_icon"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvRoadStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/ivRoadType"
|
||||
android:textSize="@dimen/sp_22"
|
||||
android:layout_marginTop="@dimen/dp_12"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:id="@+id/viewDivider"
|
||||
android:layout_width="@dimen/dp_4"
|
||||
android:layout_height="@dimen/dp_0"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:background="@color/msg_nde_road_divider"
|
||||
/>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="@dimen/dp_373"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivScan"
|
||||
android:layout_width="@dimen/dp_18"
|
||||
android:layout_height="@dimen/dp_18"
|
||||
android:layout_marginStart="@dimen/dp_18"
|
||||
android:layout_marginTop="@dimen/dp_28"
|
||||
android:src="@drawable/m2_mind_item_icon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvExplorationTitle"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_11"
|
||||
android:layout_marginTop="@dimen/dp_19"
|
||||
android:layout_marginEnd="@dimen/dp_13"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|top"
|
||||
android:textColor="@color/b2_394047"
|
||||
android:textSize="@dimen/dp_20"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivScan"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:text="@string/exploration_title" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@id/rvExplorationList"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/dp_300"
|
||||
android:layout_marginTop="@dimen/dp_14"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="@dimen/dp_29"
|
||||
app:layout_constraintLeft_toLeftOf="@id/tvExplorationTitle"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvExplorationTitle" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="@dimen/dp_373"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivNdeImage"
|
||||
android:layout_width="@dimen/dp_18"
|
||||
android:layout_height="@dimen/dp_18"
|
||||
android:layout_marginStart="@dimen/dp_18"
|
||||
android:layout_marginTop="@dimen/dp_28"
|
||||
android:src="@drawable/m2_mind_item_icon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvNdeHintContent"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_11"
|
||||
android:layout_marginTop="@dimen/dp_19"
|
||||
android:layout_marginEnd="@dimen/dp_13"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|top"
|
||||
android:textColor="@color/b2_394047"
|
||||
android:textSize="@dimen/dp_20"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivNdeImage"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="前方路口有车龙" />
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvNdeList"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/dp_140"
|
||||
android:layout_marginTop="@dimen/dp_15"
|
||||
android:layout_marginEnd="@dimen/dp_13"
|
||||
android:layout_marginStart="@dimen/dp_11"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivNdeImage"
|
||||
app:layout_constraintTop_toBottomOf="@id/ivNdeImage" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="@dimen/dp_373"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivPncImage"
|
||||
android:layout_width="@dimen/dp_18"
|
||||
android:layout_height="@dimen/dp_18"
|
||||
android:layout_marginStart="@dimen/dp_18"
|
||||
android:layout_marginTop="@dimen/dp_28"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:src="@drawable/m2_mind_item_icon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPNCHintContent"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/dp_13"
|
||||
android:layout_marginTop="@dimen/dp_19"
|
||||
android:layout_marginStart="@dimen/dp_11"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|top"
|
||||
android:textColor="@color/b2_394047"
|
||||
android:layout_marginBottom="@dimen/dp_29"
|
||||
android:textSize="@dimen/dp_20"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivPncImage"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
tools:text="前方100米有道路施工,施工长度100米,影响第1、2车道通行。正在向第3车道变道避让前方施工区域" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="@dimen/dp_373"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivZhiRoadRoamView"
|
||||
android:layout_width="@dimen/dp_18"
|
||||
android:layout_height="@dimen/dp_18"
|
||||
android:layout_marginStart="@dimen/dp_18"
|
||||
android:layout_marginTop="@dimen/dp_28"
|
||||
android:src="@drawable/m2_mind_item_icon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvRoadRoamTitle"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_11"
|
||||
android:layout_marginTop="@dimen/dp_19"
|
||||
android:layout_marginEnd="@dimen/dp_13"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|top"
|
||||
android:textColor="@color/b2_394047"
|
||||
android:textSize="@dimen/dp_20"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivZhiRoadRoamView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:text="@string/road_cross_roam_tip" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/lvRoadCrossRoamTip"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_16"
|
||||
android:layout_marginBottom="@dimen/dp_29"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="@+id/tvRoadRoamTitle"
|
||||
app:layout_constraintRight_toRightOf="@+id/tvRoadRoamTitle"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvRoadRoamTitle" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/containerEventContent"
|
||||
android:layout_width="@dimen/dp_373"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivV2XImage"
|
||||
android:layout_width="@dimen/dp_18"
|
||||
android:layout_height="@dimen/dp_18"
|
||||
android:layout_marginStart="@dimen/dp_18"
|
||||
android:layout_marginTop="@dimen/dp_28"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:src="@drawable/m2_mind_item_icon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvV2XHintContent"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/dp_13"
|
||||
android:layout_marginTop="@dimen/dp_19"
|
||||
android:layout_marginStart="@dimen/dp_11"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|top"
|
||||
android:textColor="@color/b2_394047"
|
||||
android:textSize="@dimen/dp_20"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivV2XImage"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="前方100米有道路施工,施工长度100米,影响第1、2车道通行。正在向第3车道变道避让前方施工区域" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/containerImageAndLiveVideo"
|
||||
android:layout_width="@dimen/dp_321"
|
||||
android:layout_height="@dimen/dp_207"
|
||||
android:layout_marginTop="@dimen/dp_16"
|
||||
android:layout_marginBottom="@dimen/dp_29"
|
||||
app:layout_constraintStart_toStartOf="@+id/tvV2XHintContent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/tvV2XHintContent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvV2XHintContent">
|
||||
|
||||
<com.mogo.eagle.core.function.hmi.ui.v2n.RoadV2NEventLivePlayView
|
||||
android:id="@+id/livePlayView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="visible" />
|
||||
|
||||
<com.mogo.eagle.core.utilcode.mogo.imageloader.MogoImageView
|
||||
android:id="@+id/contentImageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitXY"
|
||||
android:visibility="visible"
|
||||
app:miv_radius="@dimen/dp_16"
|
||||
app:miv_shape="round"
|
||||
tools:src="@drawable/bg_v2x_bus_station" />
|
||||
</FrameLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="@dimen/dp_6"
|
||||
android:layout_marginBottom="@dimen/dp_6"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivExplorationLoading"
|
||||
android:layout_width="@dimen/dp_20"
|
||||
android:layout_height="@dimen/dp_20"
|
||||
android:src="@drawable/icon_exploration_loading_p"
|
||||
android:contentDescription="@string/exploration_loading"
|
||||
android:layout_gravity="center_vertical"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvExplorationContent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/sp_19"
|
||||
android:textColor="@color/auto_exploration_content_p"
|
||||
android:layout_marginStart="@dimen/dp_7"
|
||||
android:layout_gravity="center_vertical"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_marginTop="@dimen/dp_6"
|
||||
android:layout_marginBottom="@dimen/dp_6"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pbRoadItemTip"
|
||||
android:layout_width="@dimen/dp_20"
|
||||
android:layout_height="@dimen/dp_20"
|
||||
android:indeterminateBehavior="repeat"
|
||||
android:indeterminateDrawable="@drawable/anim_road_cross_progress"
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivRoadItemTip"
|
||||
android:layout_width="@dimen/dp_20"
|
||||
android:layout_height="@dimen/dp_20"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/icon_road_roam_tip"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvRoadItemTip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/sp_19"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@id/ivRoadItemTip"
|
||||
android:layout_marginStart="@dimen/dp_7"
|
||||
/>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"
|
||||
android:background="@drawable/b2_mind_bg"
|
||||
android:layout_width="@dimen/dp_411"
|
||||
android:layout_height="@dimen/dp_650">
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_mind_list"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="@dimen/dp_17"
|
||||
android:layout_marginStart="@dimen/dp_19"
|
||||
android:layout_marginEnd="@dimen/dp_19"
|
||||
android:layout_marginBottom="@dimen/dp_21"
|
||||
/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:src="@drawable/b2_mind_top_shader"
|
||||
android:layout_marginTop="@dimen/dp_17"
|
||||
android:layout_width="@dimen/dp_373"
|
||||
android:layout_height="@dimen/dp_70"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginTop="@dimen/dp_34"
|
||||
android:text="MogoMind"
|
||||
android:textSize="@dimen/dp_24"
|
||||
android:textColor="@color/b2_394047"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/test1"
|
||||
android:text="测试1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/test2"
|
||||
android:text="测试2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/test3"
|
||||
android:text="测试3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
</merge>
|
||||
@@ -62,9 +62,9 @@
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:src="@drawable/m2_bottom_bg"
|
||||
android:src="@drawable/m2_map_video_bg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="1290dp"/>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,40 +4,99 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- 全览地图带站点-->
|
||||
<com.mogo.eagle.core.function.view.OverMapView
|
||||
android:id="@+id/overMapView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
app:carDrawable="@drawable/shuttle_p_m2_map_car_icon"
|
||||
app:isClearArrived="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintWidth_percent="0.6"
|
||||
app:mapStyleExtraPath="@string/shuttle_p_m2_over_map_style_extra_path"
|
||||
app:mapStylePath="@string/shuttle_p_m2_over_map_style_path"
|
||||
app:resetDrawableMarginBottom="@dimen/dp_54"
|
||||
app:resetDrawableMarginRight="@dimen/dp_34"
|
||||
app:compassDrawable="@drawable/shuttle_p_m2_amap_custom_corner"
|
||||
app:arrivedDrawable="@drawable/shuttle_p_m2_amap_arrived_road"
|
||||
app:unArrivedDrawable="@drawable/shuttle_p_m2_amap_arriving_road"
|
||||
app:mapTilt="0"
|
||||
app:leftPadding="200"
|
||||
app:topPadding="150"
|
||||
app:bottomPadding="50" />
|
||||
|
||||
<!-- 高精地图 -->
|
||||
<com.mogo.och.shuttle.weaknet.passenger.ui.widget.OchMapBizPView
|
||||
android:id="@+id/mHomeView"
|
||||
app:styleMode="MAP_STYLE_DAY_VR"
|
||||
app:carPosition="-1"
|
||||
app:default_perspective="MAP_STYLE_VR_ERHAI_B2"
|
||||
app:isWeatherEnable="false"
|
||||
app:locationIcon3DRes="@raw/m2"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_width="@dimen/dp_996"
|
||||
android:layout_height="@dimen/dp_650"/>
|
||||
android:layout_height="@dimen/dp_650">
|
||||
<!-- 高精地图 -->
|
||||
<com.mogo.och.shuttle.weaknet.passenger.ui.widget.OchMapBizPView
|
||||
android:id="@+id/mHomeView"
|
||||
app:styleMode="MAP_STYLE_DAY_VR"
|
||||
app:isWeatherEnable="false"
|
||||
app:locationIcon3DRes="@raw/m2"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_marginStart="-170dp"
|
||||
android:layout_width="@dimen/dp_996"
|
||||
android:layout_height="@dimen/dp_650"/>
|
||||
<!--虚化阴影-->
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:src="@drawable/m2_map_right_top"
|
||||
android:layout_width="@dimen/dp_430"
|
||||
android:layout_height="@dimen/dp_650"/>
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:visibility="gone"
|
||||
android:background="@drawable/b2_aip_bg"
|
||||
android:layout_marginTop="@dimen/dp_3"
|
||||
android:layout_marginEnd="@dimen/dp_1"
|
||||
android:layout_width="@dimen/dp_411"
|
||||
android:layout_height="@dimen/dp_332"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:visibility="gone"
|
||||
android:background="@drawable/b2_prediction_bg"
|
||||
android:layout_marginEnd="@dimen/dp_1"
|
||||
android:layout_marginBottom="@dimen/dp_m_1"
|
||||
android:layout_width="@dimen/dp_411"
|
||||
android:layout_height="@dimen/dp_332"/>
|
||||
|
||||
<com.mogo.och.shuttle.weaknet.passenger.ui.mind.MindView
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:background="@drawable/b2_mind_bg"
|
||||
android:layout_width="@dimen/dp_411"
|
||||
android:layout_height="@dimen/dp_650"/>
|
||||
|
||||
|
||||
<!-- 全览地图带站点-->
|
||||
<com.mogo.eagle.core.function.view.OverMapView
|
||||
android:id="@+id/overMapView"
|
||||
android:layout_width="@dimen/dp_996"
|
||||
android:layout_height="@dimen/dp_650"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:carDrawable="@drawable/shuttle_p_m2_map_car_icon"
|
||||
app:isClearArrived="false"
|
||||
app:mapStyleExtraPath="@string/shuttle_p_m2_over_map_style_extra_path"
|
||||
app:mapStylePath="@string/shuttle_p_m2_over_map_style_path"
|
||||
app:compassDrawable="@drawable/shuttle_p_m2_amap_custom_corner"
|
||||
app:arrivedDrawable="@drawable/shuttle_p_m2_amap_arrived_road"
|
||||
app:unArrivedDrawable="@drawable/shuttle_p_m2_amap_arriving_road"
|
||||
app:mapTilt="0" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/leftEndGuideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.666" />
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- <View-->
|
||||
<!-- android:background="@drawable/b2_map_top_shader"-->
|
||||
<!-- app:layout_constraintTop_toTopOf="parent"-->
|
||||
<!-- app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!-- android:layout_width="@dimen/dp_996"-->
|
||||
<!-- android:layout_height="@dimen/dp_200"/>-->
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -27,4 +27,7 @@
|
||||
<color name="m2_516582">#516582</color>
|
||||
<color name="b2_95B1D6">#95B1D6</color>
|
||||
<color name="b2_1F82FB">#1F82FB</color>
|
||||
<color name="b2_D7F1FF">#D7F1FF</color>
|
||||
<color name="b2_394047">#394047</color>
|
||||
<color name="b2_BBC9D4">#BBC9D4</color>
|
||||
</resources>
|
||||