Merge branch 'dev_robotaxi-d_240912_6.7.0' into 'tmp_6.7.0_arrow'

# Conflicts:
#   core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_bone_container.xml
This commit is contained in:
aibingbing
2024-09-14 09:54:00 +00:00
163 changed files with 4060 additions and 3878 deletions

View File

@@ -89,8 +89,8 @@ class ExamControlWindow constructor(activity: Activity): View.OnTouchListener{
it.format = PixelFormat.RGBA_8888
it.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
it.gravity = Gravity.START or Gravity.TOP
it.width = 844
it.height = 1114
it.width = 906
it.height = 1176
it.alpha = 1.0f
}
}

View File

@@ -26,6 +26,7 @@ object CrashLogAnalyticsManager {
private const val crashBranchHash = "branchHash" //Git Hash
private const val crashKeyMessage = "keyMessage" //崩溃核心信息
private const val crashIsDriver = "isDriver" //是否是司机屏
private const val crashAppVersion = "crashAppVersion" //是否是司机屏
/**
* 崩溃统计
@@ -39,7 +40,7 @@ object CrashLogAnalyticsManager {
* @param branchHash Git Hash
*/
private fun realCrashLogAnalytics(cosPath: String,type: String,plateNumber: String,carSn: String,mapVersion: String,eyeVersion: String,
appFlavor: String,branchHash: String,keyMessage: String,isDriver: Boolean){
appFlavor: String,branchHash: String,keyMessage: String,isDriver: Boolean, crashVersion: String){
val crashLogParams = HashMap<String,Any>()
crashLogParams[crashCosPath] = cosPath
crashLogParams[crashType] = type
@@ -51,6 +52,7 @@ object CrashLogAnalyticsManager {
crashLogParams[crashBranchHash] = branchHash
crashLogParams[crashKeyMessage] = keyMessage
crashLogParams[crashIsDriver] = isDriver
crashLogParams[crashAppVersion] = crashVersion
MogoAnalyticUtils.track(crashLogRecord,crashLogParams)
}
@@ -59,7 +61,7 @@ object CrashLogAnalyticsManager {
* @param crashType 崩溃类型
* @param keyMessage 崩溃关键信息
*/
fun crashLogAnalytics(crashType: String,keyMessage: String){
fun crashLogAnalytics(crashType: String, keyMessage: String, crashAppVersion: String){
val crashCosPath = StringBuilder()
crashCosPath.append("CarPad/")
if(DebugConfig.isDebug()){
@@ -74,7 +76,7 @@ object CrashLogAnalyticsManager {
realCrashLogAnalytics(crashCosPath.toString(),crashType, AppConfigInfo.plateNumber,
SharedPrefsMgr.getInstance().sn,
CallerAutoPilotStatusListenerManager.getDockerVersion() ?: "",
AppUtils.getAppVersionName(),AppConfigInfo.flavor,AppConfigInfo.workingBranchHash,keyMessage,AppConfigInfo.isDriver)
AppUtils.getAppVersionName(),AppConfigInfo.flavor,AppConfigInfo.workingBranchHash,keyMessage,AppConfigInfo.isDriver, crashAppVersion)
}
}

View File

@@ -284,7 +284,9 @@ internal class MoGoLogRecordProviderImpl: IMoGoLogRecordProvider,
NativeCrash -> "NativeCrash"
ANRCrash -> "ANRCrash"
}
CrashLogAnalyticsManager.crashLogAnalytics(typeStr, keyMessage)
val appVersion = extra?.get("App version") ?: ""
Log.d(TAG, "-- app version: $appVersion")
CrashLogAnalyticsManager.crashLogAnalytics(typeStr, keyMessage, appVersion)
} catch (e: Throwable) {
e.printStackTrace()
} finally {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 928 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -1,38 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/dp_844"
android:layout_height="@dimen/dp_1114"
android:layout_width="@dimen/dp_906"
android:layout_height="@dimen/dp_1176"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/bg_exam_control">
<View
android:id="@+id/viewTitleBg"
android:layout_width="@dimen/dp_844"
android:layout_height="@dimen/dp_102"
android:background="@drawable/bg_exam_control_title"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/viewTitleBg"
app:layout_constraintBottom_toBottomOf="@id/viewTitleBg"
app:layout_constraintLeft_toLeftOf="@id/viewTitleBg"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:text="@string/exam_vehicle_control"
android:textSize="@dimen/sp_34"
android:textColor="@color/white"
android:layout_marginStart="@dimen/dp_63"
android:layout_marginStart="@dimen/dp_94"
android:layout_marginTop="@dimen/dp_58"
/>
<ImageView
android:id="@+id/ivCloseExam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/viewTitleBg"
app:layout_constraintBottom_toBottomOf="@id/viewTitleBg"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:src="@drawable/icon_exam_close"
android:contentDescription="@string/exam_close"
@@ -40,6 +29,7 @@
android:paddingTop="@dimen/dp_30"
android:paddingBottom="@dimen/dp_30"
android:paddingStart="@dimen/dp_56"
android:layout_margin="@dimen/dp_31"
/>
<View
@@ -49,7 +39,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="@dimen/dp_142"
android:layout_marginTop="@dimen/dp_173"
android:background="@drawable/bg_exam_vehicle_mode"
/>
@@ -197,7 +187,7 @@
app:layout_constraintTop_toBottomOf="@id/viewVehicleModeBg"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="@dimen/dp_40"
android:layout_marginLeft="@dimen/dp_47"
android:layout_marginLeft="@dimen/dp_78"
android:background="@drawable/bg_exam_seat_status"
/>
@@ -269,7 +259,7 @@
app:layout_constraintRight_toRightOf="parent"
android:src="@drawable/exam_line_to_right_selector"
android:layout_marginTop="@dimen/dp_40"
android:layout_marginRight="@dimen/dp_47"
android:layout_marginRight="@dimen/dp_78"
android:contentDescription="@string/exam_line_to_right"
/>
@@ -340,6 +330,7 @@
app:layout_constraintBottom_toBottomOf="parent"
android:src="@drawable/exam_emergency_stop_selector"
android:contentDescription="@string/exam_emergency_stop"
android:layout_marginBottom="@dimen/dp_31"
/>

View File

@@ -3,8 +3,12 @@ package com.mogo.eagle.core.function.hmi.bone
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.eagle.core.function.hmi.R
import kotlinx.android.synthetic.main.view_bone_container.view.clBoneBiz
import kotlinx.android.synthetic.main.view_bone_container.view.clBoneTab
import kotlinx.android.synthetic.main.view_bone_tab.view.carInfoTabView
class BoneContainerView @JvmOverloads constructor(
context: Context,
@@ -17,9 +21,27 @@ class BoneContainerView @JvmOverloads constructor(
initView()
}
private fun initView() {
private var logOut: (() -> Unit)? = null
private fun initView() {
clBoneTab.loginOut {
logOut?.invoke()
}
}
fun addBizView(view: View) {
clBoneBiz.addView(view)
}
fun setCarNo(carNo: String){
clBoneTab.setCarNo(carNo)
}
fun setLoginInfo(loginNo: String){
clBoneTab.setLoginInfo(loginNo)
}
fun loginOut(logOut:(() -> Unit)){
this.logOut = logOut
}
}

View File

@@ -42,6 +42,8 @@ class BoneTabLayout @JvmOverloads constructor(
}
}
private var logOut:(() -> Unit)? = null
init {
LayoutInflater.from(context).inflate(R.layout.view_bone_tab, this, true)
initView()
@@ -60,6 +62,23 @@ class BoneTabLayout @JvmOverloads constructor(
tabSwitchMore.setOnClickListener {
updateTabType(TabType.MORE_INFO)
}
carInfoTabView.loginOut {
logOut?.invoke()
}
}
fun setCarNo(carNo: String){
carInfoTabView.setCarNo(carNo)
}
fun setLoginInfo(loginNo: String){
carInfoTabView.setLoginInfo(loginNo)
}
fun loginOut(logOut:(() -> Unit)){
this.logOut = logOut
}
private fun updateTabType(changeType: TabType) {
@@ -108,4 +127,5 @@ class BoneTabLayout @JvmOverloads constructor(
else -> {}
}
}
}

View File

@@ -18,8 +18,6 @@ class TabSwitchView @JvmOverloads constructor(
private var tabDefaultRes = -1
private var tabClickRes = -1
private var tabClickBgRes = -1
private var isCheck = false
init {
@@ -28,7 +26,6 @@ class TabSwitchView @JvmOverloads constructor(
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.TabSwitch)
tabDefaultRes = typedArray.getResourceId(R.styleable.TabSwitch_defaultRes, -1)
tabClickRes = typedArray.getResourceId(R.styleable.TabSwitch_clickRes, -1)
tabClickBgRes = typedArray.getResourceId(R.styleable.TabSwitch_clickBgRes, -1)
typedArray.recycle()
} catch (e: Exception) {
e.printStackTrace()
@@ -39,7 +36,6 @@ class TabSwitchView @JvmOverloads constructor(
private fun initView() {
ivTabDefault.setImageResource(tabDefaultRes)
ivTabClick.setImageResource(tabClickRes)
ivTabClickBg.setImageResource(tabClickBgRes)
}
fun switchTab(isCheck: Boolean) {

View File

@@ -0,0 +1,282 @@
package com.mogo.eagle.core.function.hmi.map
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.constraintlayout.widget.ConstraintLayout
class ExchangeChildLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
private var mContext: Context? = null
private var isChange = false
private var isPlayingAnim = false
private var maxWidth = 0
private var maxHeight = 0
private var minWidth = 0
private var minHeight = 0
private var bottomX = 0f
private var bottomY = 0f
private var topX = 0f
private var topY = 0f
companion object {
private const val TAG = "ExchangeChildLayout"
private const val ANIM_DURATION = 600L
}
init {
try {
initView(context)
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun initView(context: Context) {
mContext = context
}
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
if (hasWindowFocus) {
val bottomView = getChildAt(0)
val topView = getChildAt(childCount - 1)
maxWidth = bottomView.width
maxHeight = bottomView.height
minWidth = topView.width
minHeight = topView.height
bottomX = bottomView.x
bottomY = bottomView.y
topX = topView.x
topY = topView.y
}
}
/**
* 开启ViewGroup自定义绘制顺序
*/
fun setCustomOrder(enable: Boolean) {
isChildrenDrawingOrderEnabled = enable
}
/**
* 切换高精地图和高德地图View的位置
*/
fun exchange() {
if (!isPlayingAnim) {
isChange = !isChange
startAnim()
invalidate()
}
}
private fun startAnim() {
val bottomView = getChildAt(0)
val topView = getChildAt(childCount - 1)
val bottomXAnimator: ObjectAnimator
val bottomYAnimator: ObjectAnimator
val bottomWidthAnimator: ObjectAnimator
val bottomHeightAnimator: ObjectAnimator
val topXAnimator: ObjectAnimator
val topYAnimator: ObjectAnimator
val topWidthAnimator: ObjectAnimator
val topHeightAnimator: ObjectAnimator
if (isChange) {
exchangeRule(bottomView.layoutParams as LayoutParams, true, true)
bottomXAnimator = ObjectAnimator.ofFloat(bottomView, "x", bottomX, topX)
bottomYAnimator = ObjectAnimator.ofFloat(bottomView, "y", bottomY, topY)
bottomWidthAnimator =
ObjectAnimator.ofInt(
WrapperViewWidth(bottomView),
"width",
maxWidth,
minWidth
)
bottomHeightAnimator =
ObjectAnimator.ofInt(
WrapperViewHeight(bottomView),
"height",
maxHeight,
minHeight
)
exchangeRule(topView.layoutParams as LayoutParams, false, true)
topXAnimator = ObjectAnimator.ofFloat(topView, "x", topX, bottomX)
topYAnimator = ObjectAnimator.ofFloat(topView, "y", topY, bottomY)
topWidthAnimator =
ObjectAnimator.ofInt(
WrapperViewWidth(topView),
"width",
minWidth,
maxWidth
)
topHeightAnimator =
ObjectAnimator.ofInt(
WrapperViewHeight(topView),
"height",
minHeight,
maxHeight
)
} else {
exchangeRule(bottomView.layoutParams as LayoutParams, true, false)
bottomXAnimator = ObjectAnimator.ofFloat(bottomView, "x", topX, bottomX)
bottomYAnimator = ObjectAnimator.ofFloat(bottomView, "y", topY, bottomY)
bottomWidthAnimator =
ObjectAnimator.ofInt(
WrapperViewWidth(bottomView),
"width",
minWidth,
maxWidth
)
bottomHeightAnimator =
ObjectAnimator.ofInt(
WrapperViewHeight(bottomView),
"height",
minHeight,
maxHeight
)
exchangeRule(topView.layoutParams as LayoutParams, false, false)
topXAnimator = ObjectAnimator.ofFloat(topView, "x", bottomX, topX)
topYAnimator = ObjectAnimator.ofFloat(topView, "y", bottomY, topY)
topWidthAnimator =
ObjectAnimator.ofInt(
WrapperViewWidth(topView),
"width",
maxWidth,
minWidth
)
topHeightAnimator =
ObjectAnimator.ofInt(
WrapperViewHeight(topView),
"height",
maxHeight,
minHeight
)
}
// 将多个动画组合在一起
val animatorSet = AnimatorSet()
animatorSet.playTogether(
bottomXAnimator,
bottomYAnimator,
bottomWidthAnimator,
bottomHeightAnimator,
topXAnimator,
topYAnimator,
topWidthAnimator,
topHeightAnimator
)
animatorSet.addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator) {
isPlayingAnim = true
}
override fun onAnimationEnd(animation: Animator) {
isPlayingAnim = false
}
override fun onAnimationCancel(animation: Animator) {
isPlayingAnim = false
}
override fun onAnimationRepeat(animation: Animator) {
}
})
animatorSet.duration = ANIM_DURATION
animatorSet.interpolator = AccelerateDecelerateInterpolator()
// 启动动画
animatorSet.start()
}
fun getChangeFlag() = isChange
override fun isChildrenDrawingOrderEnabled() = super.isChildrenDrawingOrderEnabled()
override fun getChildDrawingOrder(childCount: Int, i: Int): Int {
return if (isChange) {
when (i) {
0 -> {
childCount - 1
}
childCount - 1 -> {
0
}
else -> {
i
}
}
} else {
super.getChildDrawingOrder(childCount, i)
}
}
// 用于包装 View 的宽度,以便可以使用 ObjectAnimator 来改变宽度
class WrapperViewWidth(
private val view: View,
) {
var width: Int
get() = view.layoutParams.width
set(width) {
val layoutParams = view.layoutParams as LayoutParams
layoutParams.width = width
view.layoutParams = layoutParams
}
}
class WrapperViewHeight(
private val view: View,
) {
var height: Int
get() = view.layoutParams.height
set(height) {
val layoutParams = view.layoutParams as LayoutParams
layoutParams.height = height
view.layoutParams = layoutParams
}
}
private fun exchangeRule(
layoutParams: LayoutParams, isBottom: Boolean,
isChange: Boolean
) {
if (isBottom) {
if (isChange) {
layoutParams.startToStart = LayoutParams.UNSET
layoutParams.topToTop = LayoutParams.UNSET
layoutParams.endToEnd = LayoutParams.PARENT_ID
layoutParams.bottomToBottom = LayoutParams.PARENT_ID
} else {
layoutParams.startToStart = LayoutParams.PARENT_ID
layoutParams.topToTop = LayoutParams.PARENT_ID
layoutParams.endToEnd = LayoutParams.UNSET
layoutParams.bottomToBottom = LayoutParams.UNSET
}
} else {
if (isChange) {
layoutParams.startToStart = LayoutParams.PARENT_ID
layoutParams.topToTop = LayoutParams.PARENT_ID
layoutParams.endToEnd = LayoutParams.UNSET
layoutParams.bottomToBottom = LayoutParams.UNSET
} else {
layoutParams.startToStart = LayoutParams.UNSET
layoutParams.topToTop = LayoutParams.UNSET
layoutParams.endToEnd = LayoutParams.PARENT_ID
layoutParams.bottomToBottom = LayoutParams.PARENT_ID
}
}
}
}

View File

@@ -7,6 +7,7 @@ import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.mogo.eagle.core.data.config.HmiBuildConfig
import com.mogo.eagle.core.data.enums.DataSourceType
@@ -21,9 +22,8 @@ import com.mogo.eagle.core.function.call.v2x.CallerTrafficLightListenerManager
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_HMI
import com.mogo.eagle.core.utilcode.util.ThreadUtils.*
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import kotlinx.android.synthetic.main.hmi_view_traffic_light.view.*
import me.jessyan.autosize.utils.AutoSizeUtils
/**
* 新版红绿灯view
@@ -39,11 +39,14 @@ class SingleTrafficLightView @JvmOverloads constructor(
private const val TAG = "SingleTrafficLightView"
}
private var mLightIconIV: ImageView? = null
private var mLightIconBG: ImageView? = null
private var mLightTimeTV: GradientTextView? = null
private var mLightSourceTV: TextView? = null
private var mLightSourceDivider: View? = null
private var mLightIconIV: ImageView? = null //红绿灯Icon
private var mLightIconBG: ImageView? = null //乘客屏红绿灯背景
private var mTrafficLightClBG: ConstraintLayout ?= null //司机端红绿灯背景
private var mLightTimeTV: TypefaceTextView ?= null //司机端红绿灯倒计时
private var mLightTimeTVP: GradientTextView? = null //乘客屏红绿灯倒计时
private var mLightSourceTV: TextView? = null //红绿灯来源
private var mLightSourceDivider: View? = null //分割线
private var mCurrentLightId = TrafficLightEnum.BLACK
private var fusionTrafficLightState: Boolean = false //当前是否有融合红绿灯展示
@@ -52,8 +55,8 @@ class SingleTrafficLightView @JvmOverloads constructor(
init{
context?.let {
val typedArray = it.obtainStyledAttributes(attrs, R.styleable.TrafficLightView)
trafficLightUser = typedArray.getInt(R.styleable.TrafficLightView_traffic_light_user,0)
val typedArray = it.obtainStyledAttributes(attrs, R.styleable.SingleTrafficLightView)
trafficLightUser = typedArray.getInt(R.styleable.SingleTrafficLightView_traffic_light_user,0)
typedArray.recycle()
}
@@ -67,19 +70,24 @@ class SingleTrafficLightView @JvmOverloads constructor(
LayoutInflater.from(context).inflate(R.layout.hmi_view_traffic_light, this, true)
}
mLightIconIV = findViewById(R.id.hmi_traffic_light_iv)
mLightIconBG = findViewById(R.id.hmi_traffic_light_bg)
mLightTimeTV = findViewById(R.id.hmi_traffic_light_time_tv)
mLightSourceTV = findViewById(R.id.hmi_traffic_light_source)
mLightSourceDivider = findViewById(R.id.hmi_traffic_light_divider)
if(trafficLightUser==1){
mLightIconBG = findViewById(R.id.hmi_traffic_light_bg)
mLightTimeTVP = findViewById(R.id.hmi_traffic_light_time_tv_p)
}else{
mTrafficLightClBG = findViewById(R.id.hmi_traffic_light_cl_bg)
mLightTimeTV = findViewById(R.id.hmi_traffic_light_time_tv)
}
CallerSkinModeListenerManager.addListener(TAG, this)
CallerTrafficLightListenerManager.addListener(TAG, this)
CallerHmiViewControlListenerManager.addListener(TrafficLightView_TAG, this)
if(trafficLightUser==1){
hmi_traffic_light_bg.setBackgroundResource(R.drawable.traffic_light_bg_taxi_p)
hmi_traffic_light_source.setTextColor(ContextCompat.getColor(context,R.color.color_FF213757))
hmi_traffic_light_divider.setBackgroundColor(ContextCompat.getColor(context,R.color.color_CC5C71AB))
mLightIconBG?.setBackgroundResource(R.drawable.traffic_light_bg_taxi_p)
mLightSourceTV?.setTextColor(ContextCompat.getColor(context,R.color.color_FF213757))
mLightSourceDivider?.setBackgroundColor(ContextCompat.getColor(context,R.color.color_CC5C71AB))
}
}
@@ -96,20 +104,7 @@ class SingleTrafficLightView @JvmOverloads constructor(
}
override fun onSkinModeChange(skinMode: Int) {
runOnUiThread {
when (skinMode) {
0 -> {
hmi_traffic_light_bg.setBackgroundResource(R.drawable.traffic_light_bg)
hmi_traffic_light_source.setTextColor(ContextCompat.getColor(context,R.color.color_FFFFFF))
hmi_traffic_light_divider.setBackgroundColor(ContextCompat.getColor(context,R.color.color_FFFFFF))
}
1 -> {
hmi_traffic_light_bg.setBackgroundResource(R.drawable.traffic_light_bg_day_light)
hmi_traffic_light_source.setTextColor(ContextCompat.getColor(context,R.color.color_2D3E5F))
hmi_traffic_light_divider.setBackgroundColor(ContextCompat.getColor(context,R.color.color_2D3E5F))
}
}
}
//TODO 670版本UI改版没有设计白天黑夜模式暂时关闭
}
/**
@@ -158,30 +153,27 @@ class SingleTrafficLightView @JvmOverloads constructor(
}
}
/**
* 关闭红绿灯计数
*/
override fun disableTrafficLightCountDown() {
super.disableTrafficLightCountDown()
UiThreadHandler.post {
// 小巴车的司机端需要展示红绿灯信号来源
// if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
// && AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)){
val lp = this.layoutParams as MarginLayoutParams
lp.width = context.resources.getDimension(R.dimen.dp_325).toInt()
this.layoutParams = lp
mLightSourceTV!!.visibility = VISIBLE
mLightSourceDivider!!.visibility = VISIBLE
mLightTimeTV!!.visibility = GONE
mLightSourceTV!!.setPadding(0, 0, 75, 0)
mLightIconBG!!.layoutParams.width =
context.resources.getDimension(R.dimen.dp_310).toInt()
// }else{
// val lp = this.layoutParams as MarginLayoutParams
// lp.width = context.resources.getDimension(R.dimen.hmi_traffic_light_icon_size).toInt()
// this.layoutParams = lp
// mLightTimeTV!!.visibility = GONE
// mLightSourceDivider!!.visibility = View.GONE
// mLightSourceTV!!.visibility = View.GONE
// mLightIconBG!!.layoutParams.width = context.resources.getDimension(R.dimen.dp_124).toInt()
// }
if(trafficLightUser==1){
//乘客屏
val lp = this.layoutParams as MarginLayoutParams
lp.width = context.resources.getDimension(R.dimen.dp_325).toInt()
this.layoutParams = lp
mLightSourceTV?.visibility = VISIBLE
mLightSourceDivider!!.visibility = VISIBLE
mLightTimeTVP?.visibility = GONE
mLightSourceTV?.setPadding(0, 0, 75, 0)
mLightIconBG?.layoutParams?.width =
context.resources.getDimension(R.dimen.dp_310).toInt()
}else{
//司机屏
//TODO
}
}
}
@@ -198,7 +190,13 @@ class SingleTrafficLightView @JvmOverloads constructor(
TrafficLightEnum.RED -> changeCountdownRed(redNum)
TrafficLightEnum.YELLOW -> changeCountdownYellow(yellowNum)
TrafficLightEnum.GREEN -> changeCountdownGreen(greenNum)
else -> UiThreadHandler.post { mLightTimeTV!!.text = "" }
else -> UiThreadHandler.post {
if(trafficLightUser == 1){
mLightTimeTVP?.text = ""
}else{
mLightTimeTV?.text = ""
}
}
}
}
}
@@ -208,27 +206,25 @@ class SingleTrafficLightView @JvmOverloads constructor(
UiThreadHandler.post {
if (redNum > 0) {
resetView()
mLightTimeTV!!.setVertical(true)
if(trafficLightUser == 1){
mLightTimeTV!!.setColorList(
mLightTimeTVP?.setVertical(true)
mLightTimeTVP?.setColorList(
intArrayOf(
ContextCompat.getColor(context,R.color.color_FF384D6E),
ContextCompat.getColor(context,R.color.color_FF384D6E)
)
)
mLightTimeTVP?.text = redNum.toString()
}else{
mLightTimeTV!!.setColorList(
intArrayOf(
ContextCompat.getColor(context,R.color.hmi_traffic_light_red_color_up),
ContextCompat.getColor(context,R.color.hmi_traffic_light_red_color_down)
)
)
mLightTimeTV?.text = redNum.toString()
}
mLightTimeTV!!.text = redNum.toString()
} else {
disableTrafficLightCountDown()
mLightTimeTV!!.text = ""
if(trafficLightUser == 1){
mLightTimeTVP?.text = ""
}else{
mLightTimeTV?.text = ""
}
}
}
}
@@ -238,26 +234,26 @@ class SingleTrafficLightView @JvmOverloads constructor(
UiThreadHandler.post {
if (greenNum > 0) {
resetView()
mLightTimeTV!!.setVertical(true)
if(trafficLightUser == 1){
mLightTimeTV!!.setColorList(
mLightTimeTVP?.setVertical(true)
mLightTimeTVP?.setColorList(
intArrayOf(
ContextCompat.getColor(context,R.color.color_FF384D6E),
ContextCompat.getColor(context,R.color.color_FF384D6E)
)
)
mLightTimeTVP?.text = greenNum.toString()
}else{
mLightTimeTV!!.setColorList(
intArrayOf(
ContextCompat.getColor(context,R.color.hmi_traffic_light_green_color_up),
ContextCompat.getColor(context,R.color.hmi_traffic_light_green_color_down)
)
)
mLightTimeTV?.text = greenNum.toString()
}
mLightTimeTV!!.text = greenNum.toString()
} else {
disableTrafficLightCountDown()
mLightTimeTV!!.text = ""
if(trafficLightUser == 1){
mLightTimeTVP!!.text = ""
}else{
mLightTimeTV!!.text = ""
}
}
}
}
@@ -267,26 +263,25 @@ class SingleTrafficLightView @JvmOverloads constructor(
UiThreadHandler.post {
if (yellowNum > 0) {
resetView()
mLightTimeTV!!.setVertical(true)
if(trafficLightUser == 1){
mLightTimeTV!!.setColorList(
mLightTimeTVP?.setVertical(true)
mLightTimeTVP?.setColorList(
intArrayOf(
ContextCompat.getColor(context,R.color.color_FF384D6E),
ContextCompat.getColor(context,R.color.color_FF384D6E)
)
)
mLightTimeTVP?.text = yellowNum.toString()
}else{
mLightTimeTV!!.setColorList(
intArrayOf(
ContextCompat.getColor(context,R.color.hmi_traffic_light_yellow_color_up),
ContextCompat.getColor(context,R.color.hmi_traffic_light_yellow_color_down)
)
)
mLightTimeTV?.text = yellowNum.toString()
}
mLightTimeTV!!.text = yellowNum.toString()
} else {
disableTrafficLightCountDown()
mLightTimeTV!!.text = ""
if(trafficLightUser == 1){
mLightTimeTVP?.text = ""
}else{
mLightTimeTV?.text = ""
}
}
}
}
@@ -332,50 +327,56 @@ class SingleTrafficLightView @JvmOverloads constructor(
else -> this@SingleTrafficLightView.visibility = GONE
}
when (lightSource) {
//TODO 司机屏展示来源需要更改文案
DataSourceType.AICLOUD -> {
mLightSourceTV!!.text = context.getString(R.string.light_source_ai_cloud)
if(trafficLightUser == 1){
mLightSourceTV?.text = context.getString(R.string.light_source_ai_cloud)
}else{
mLightSourceTV?.text = context.getString(R.string.light_source_driver_ai_cloud)
}
}
DataSourceType.TELEMATIC_UNION_V2I,
DataSourceType.TELEMATIC_UNION_V2N,
DataSourceType.TELEMATIC -> {
mLightSourceTV!!.text = context.getString(R.string.light_source_perception)
}
DataSourceType.TELEMATIC_UNION_V2I -> {
mLightSourceTV!!.text = context.getString(R.string.light_source_perception_v2i)
}
DataSourceType.TELEMATIC_UNION_V2N -> {
mLightSourceTV!!.text = context.getString(R.string.light_source_perception_v2n)
if(trafficLightUser == 1){
mLightSourceTV?.text = context.getString(R.string.light_source_perception)
}else{
mLightSourceTV?.text = context.getString(R.string.light_source_driver_perception)
}
}
DataSourceType.OBU -> {
mLightSourceTV!!.text = context.getString(R.string.light_source_obu)
if(trafficLightUser == 1){
mLightSourceTV?.text = context.getString(R.string.light_source_obu)
}else{
mLightSourceTV?.text = context.getString(R.string.light_source_driver_obu)
mLightSourceTV?.textSize = AutoSizeUtils.sp2px(context, 23f).toFloat()
mLightSourceTV?.setLineSpacing(0f, 1.0f)
}
}
else -> {
mLightSourceTV!!.visibility = GONE
mLightSourceTV?.visibility = GONE
}
}
}
private fun resetView() {
// 小巴车的司机端需要展示红绿灯信号来源 ,由于需要知道来源,这里不在限制
// if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
// && AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)){
val lp = this.layoutParams as MarginLayoutParams
lp.width =
context.resources.getDimension(R.dimen.hmi_traffic_light_bus_layout_width).toInt()
this.layoutParams = lp
mLightTimeTV!!.visibility = View.VISIBLE
mLightSourceDivider!!.visibility = View.VISIBLE
mLightSourceTV!!.visibility = View.VISIBLE
mLightSourceTV!!.setPadding(0, 0, 0, 0)
mLightIconBG!!.layoutParams.width =
context.resources.getDimension(R.dimen.hmi_traffic_light_bus_bg_width).toInt()
// }else{
// val lp = this.layoutParams as MarginLayoutParams
// lp.width = context.resources.getDimension(R.dimen.hmi_traffic_light_layout_width).toInt()
// this.layoutParams = lp
// mLightTimeTV!!.visibility = View.VISIBLE
// mLightSourceDivider!!.visibility = View.GONE
// mLightSourceTV!!.visibility = View.GONE
// mLightIconBG!!.layoutParams.width = context.resources.getDimension(R.dimen.hmi_traffic_light_bg_width).toInt()
// }
if(trafficLightUser == 1){
//乘客屏
val lp = this.layoutParams as MarginLayoutParams
lp.width =
context.resources.getDimension(R.dimen.hmi_traffic_light_bus_layout_width).toInt()
this.layoutParams = lp
mLightTimeTV!!.visibility = View.VISIBLE
mLightSourceDivider!!.visibility = View.VISIBLE
mLightSourceTV!!.visibility = View.VISIBLE
mLightSourceTV!!.setPadding(0, 0, 0, 0)
mLightIconBG!!.layoutParams.width =
context.resources.getDimension(R.dimen.hmi_traffic_light_bus_bg_width).toInt()
}else{
//司机屏
//TODO
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 977 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 770 B

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -1,60 +1,58 @@
<?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"
android:layout_width="@dimen/hmi_traffic_light_bus_layout_width"
android:layout_height="@dimen/hmi_traffic_light_layout_height"
xmlns:tools="http://schemas.android.com/tools"
android:visibility="visible">
<ImageView
android:id="@+id/hmi_traffic_light_bg"
android:layout_width="@dimen/hmi_traffic_light_bus_bg_width"
android:layout_height="@dimen/hmi_traffic_light_bg_height"
android:layout_marginStart="@dimen/hmi_traffic_light_bg_margin_left"
android:layout_marginTop="@dimen/hmi_traffic_light_bg_margin_top"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
android:id="@+id/hmi_traffic_light_cl_bg"
android:layout_width="@dimen/dp_368"
android:layout_height="@dimen/dp_180"
android:background="@drawable/icon_single_traffic_light_bg"
>
<ImageView
android:id="@+id/hmi_traffic_light_iv"
android:layout_width="@dimen/hmi_traffic_light_icon_size"
android:layout_height="@dimen/hmi_traffic_light_icon_size"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.mogo.eagle.core.function.hmi.ui.widget.GradientTextView
android:id="@+id/hmi_traffic_light_time_tv"
android:layout_width="@dimen/hmi_traffic_light_time_view_width"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="@dimen/hmi_traffic_light_time_size"
android:textStyle="bold"
android:layout_width="@dimen/dp_140"
android:layout_height="@dimen/dp_140"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:contentDescription="@string/traffic_light_status"
android:layout_marginStart="@dimen/dp_20"
/>
<com.mogo.eagle.core.function.hmi.ui.widget.TypefaceTextView
android:id="@+id/hmi_traffic_light_time_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/hmi_traffic_light_iv"
android:layout_marginStart="-40dp"
android:textColor="@color/white"
android:textSize="@dimen/sp_80"
app:textType="DS_DIGIB_2"
/>
<View
android:id="@+id/hmi_traffic_light_divider"
android:layout_width="@dimen/dp_2"
android:layout_height="@dimen/dp_80"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="#999999"
app:layout_constraintRight_toLeftOf="@id/hmi_traffic_light_source"
android:layout_marginEnd="@dimen/dp_20"
/>
<TextView
android:id="@+id/hmi_traffic_light_source"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="自车感知"
android:textSize="@dimen/hmi_traffic_light_source_size"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginEnd="@dimen/dp_30"
android:orientation="vertical"
android:textSize="@dimen/sp_32"
android:textColor="@color/white"
android:layout_marginEnd="@dimen/dp_65"
/>
<View
android:id="@+id/hmi_traffic_light_divider"
android:layout_width="@dimen/dp_1"
android:layout_height="@dimen/dp_47"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="@id/hmi_traffic_light_source"
android:layout_marginEnd="@dimen/dp_25"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -28,7 +28,7 @@
/>
<com.mogo.eagle.core.function.hmi.ui.widget.GradientTextView
android:id="@+id/hmi_traffic_light_time_tv"
android:id="@+id/hmi_traffic_light_time_tv_p"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"

View File

@@ -1,16 +1,16 @@
<?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_15"
android:layout_marginBottom="@dimen/dp_15"
>
android:layout_marginTop="@dimen/dp_17"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/ivExplorationLoading"
android:layout_width="@dimen/dp_27"
android:layout_height="@dimen/dp_27"
android:layout_width="@dimen/dp_29"
android:layout_height="@dimen/dp_29"
android:src="@drawable/icon_exploration_loading"
android:contentDescription="@string/exploration_loading"
android:layout_gravity="center_vertical"
@@ -20,9 +20,9 @@
android:id="@+id/tvExplorationContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/sp_20"
android:textSize="@dimen/sp_26"
android:textColor="@color/white"
android:layout_marginLeft="@dimen/dp_13"
android:layout_marginStart="@dimen/dp_13"
android:layout_gravity="center_vertical"
/>

View File

@@ -1,24 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/dp_600"
android:layout_height="@dimen/dp_520"
android:layout_width="@dimen/dp_694"
android:layout_height="@dimen/dp_509"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/bg_auto_exploration">
<ImageView
android:id="@+id/ivScan"
android:layout_width="@dimen/dp_100"
android:layout_height="@dimen/dp_100"
android:layout_width="@dimen/dp_120"
android:layout_height="@dimen/dp_120"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:src="@drawable/icon_exploration_scan"
android:contentDescription="@string/exploration_scan"
android:layout_margin="@dimen/dp_20"
android:layout_margin="@dimen/dp_50"
/>
<ImageView
android:layout_width="@dimen/dp_75"
android:layout_height="@dimen/dp_75"
android:layout_width="@dimen/dp_64"
android:layout_height="@dimen/dp_44"
app:layout_constraintTop_toTopOf="@id/ivScan"
app:layout_constraintBottom_toBottomOf="@id/ivScan"
app:layout_constraintLeft_toLeftOf="@id/ivScan"
@@ -33,9 +33,9 @@
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="@dimen/dp_31"
android:layout_marginLeft="@dimen/dp_146"
android:textSize="@dimen/sp_30"
android:layout_marginTop="@dimen/dp_55"
android:layout_marginLeft="@dimen/dp_190"
android:textSize="@dimen/sp_40"
android:textColor="@color/white"
android:text="@string/exploration_title"
/>
@@ -46,7 +46,7 @@
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/tvExplorationTitle"
app:layout_constraintLeft_toLeftOf="@id/tvExplorationTitle"
android:layout_marginTop="@dimen/dp_17"
android:layout_marginTop="@dimen/dp_4"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -23,7 +23,6 @@
android:layout_marginTop="@dimen/dp_385"
android:elevation="1dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.mogo.eagle.core.function.hmi.bone.BoneTabLayout

View File

@@ -17,20 +17,20 @@
android:layout_width="@dimen/dp_960"
android:layout_height="@dimen/dp_1137"
android:layout_marginStart="@dimen/dp_40"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_224"
android:layout_marginStart="@dimen/dp_20"
android:layout_marginBottom="@dimen/dp_m_2"
android:layout_width="@dimen/dp_960"
android:layout_height="@dimen/dp_216"
android:layout_marginBottom="@dimen/dp_8"
android:background="@drawable/bg_tab_switch"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
android:layout_marginStart="@dimen/dp_20"
app:layout_constraintLeft_toLeftOf="parent">
<com.mogo.eagle.core.function.hmi.bone.TabSwitchView
android:id="@+id/tabSwitchCarInfo"
@@ -38,7 +38,6 @@
android:layout_height="@dimen/dp_140"
android:layout_marginStart="@dimen/dp_40"
android:layout_marginTop="@dimen/dp_20"
app:clickBgRes="@drawable/icon_tab_click_bg"
app:clickRes="@drawable/icon_tab_car_info_click"
app:defaultRes="@drawable/icon_tab_car_info"
app:layout_constraintLeft_toLeftOf="parent"
@@ -49,7 +48,6 @@
android:layout_width="@dimen/dp_220"
android:layout_height="@dimen/dp_140"
android:layout_marginTop="@dimen/dp_20"
app:clickBgRes="@drawable/icon_tab_click_bg"
app:clickRes="@drawable/icon_tab_msg_box_click"
app:defaultRes="@drawable/icon_tab_msg_box"
app:layout_constraintLeft_toRightOf="@+id/tabSwitchCarInfo"
@@ -60,7 +58,6 @@
android:layout_width="@dimen/dp_220"
android:layout_height="@dimen/dp_140"
android:layout_marginTop="@dimen/dp_20"
app:clickBgRes="@drawable/icon_tab_click_bg"
app:clickRes="@drawable/icon_tab_report_click"
app:defaultRes="@drawable/icon_tab_report"
app:layout_constraintLeft_toRightOf="@+id/tabSwitchMsgBox"
@@ -71,7 +68,6 @@
android:layout_width="@dimen/dp_220"
android:layout_height="@dimen/dp_140"
android:layout_marginTop="@dimen/dp_20"
app:clickBgRes="@drawable/icon_tab_click_bg"
app:clickRes="@drawable/icon_tab_more_click"
app:defaultRes="@drawable/icon_tab_more"
app:layout_constraintLeft_toRightOf="@+id/tabSwitchReport"

View File

@@ -30,8 +30,10 @@
<ImageView
android:id="@+id/ivTabClickBg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="@dimen/dp_220"
android:layout_height="@dimen/dp_140"
android:scaleType="fitXY"
android:src="@drawable/icon_tab_click_bg"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"

View File

@@ -77,7 +77,7 @@
</attr>
</declare-styleable>
<declare-styleable name="TrafficLightView">
<declare-styleable name="SingleTrafficLightView">
<attr name="traffic_light_user">
<enum name="traffic_light_taxi_p" value="1" />
</attr>
@@ -155,7 +155,6 @@
<declare-styleable name="TabSwitch" >
<attr name="defaultRes" format="reference"/>
<attr name="clickRes" format="reference"/>
<attr name="clickBgRes" format="reference"/>
</declare-styleable>
</resources>

View File

@@ -98,12 +98,17 @@
<string name="hint_exit_app_again">再按一次退出应用</string>
<!--消息盒子V2X消息Title-->
<string name="v2x_title_content">%s-%s</string>
<string name="traffic_light_status">红绿灯灯态</string>
<!--红绿灯数据来源-->
<string name="light_source_ai_cloud">云端下发</string>
<string name="light_source_driver_ai_cloud">云\n端</string>
<string name="light_source_perception">自车感知</string>
<string name="light_source_driver_perception">自\n车</string>
<string name="light_source_perception_v2i">融合V2I</string>
<string name="light_source_perception_v2n">融合V2N</string>
<string name="light_source_obu">\u2000OBU\u2000</string>
<string name="light_source_driver_obu">O\nB\nU</string>
<string name="parallel_drive">远程代驾</string>
<string name="parallel_drive_requesting">请求中...</string>
<string name="parallel_drive_synchronizing">同步中...</string>