增加CallerHmiManager.INSTANCE.setProxyNotificationView(view)设置HMI中V2X弹窗预警,参考V2XNotificationView初始化方式

Signed-off-by: donghongyu <donghongyu@zhidaoauto.com>
This commit is contained in:
donghongyu
2022-03-16 12:56:44 +08:00
parent 3ccec25a8f
commit 15281b6b76
14 changed files with 212 additions and 123 deletions

View File

@@ -6,11 +6,10 @@ import android.view.View
import androidx.appcompat.view.ContextThemeWrapper
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import com.mogo.eagle.core.function.hmi.notification.enums.SidePattern
import com.mogo.eagle.core.data.enums.SidePattern
import com.mogo.eagle.core.function.hmi.notification.interfaces.OnFloatAnimator
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_HMI
import com.mogo.eagle.core.utilcode.reminder.Reminder
import com.mogo.eagle.core.utilcode.reminder.api.impl.ViewReminder

View File

@@ -12,7 +12,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import com.mogo.eagle.core.function.hmi.notification.anim.AnimatorManager
import com.mogo.eagle.core.function.hmi.notification.enums.ShowPattern
import com.mogo.eagle.core.data.enums.ShowPattern
import com.mogo.eagle.core.function.hmi.notification.widget.ParentFrameLayout
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_HMI

View File

@@ -3,8 +3,8 @@ package com.mogo.eagle.core.function.hmi.notification
import android.view.View
import android.view.WindowManager
import com.mogo.eagle.core.function.hmi.notification.anim.DefaultAnimator
import com.mogo.eagle.core.function.hmi.notification.enums.ShowPattern
import com.mogo.eagle.core.function.hmi.notification.enums.SidePattern
import com.mogo.eagle.core.data.enums.ShowPattern
import com.mogo.eagle.core.data.enums.SidePattern
import com.mogo.eagle.core.function.hmi.notification.interfaces.OnFloatAnimator
import com.mogo.eagle.core.function.hmi.notification.interfaces.OnFloatCallbacks
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
@@ -16,55 +16,55 @@ import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
*/
data class WarningNotificationConfig(
// 浮窗的xml布局文件
var layoutId: Int? = null,
var layoutView: View? = null,
var layoutId: Int? = null,
var layoutView: View? = null,
// 当前浮窗的tag
var floatTag: String? = null,
var floatTag: String? = null,
// 是否正在执行动画
var isAnim: Boolean = false,
var isAnim: Boolean = false,
// 是否显示
var isShow: Boolean = false,
var isShow: Boolean = false,
// 状态栏沉浸
var immersionStatusBar: Boolean = false,
var immersionStatusBar: Boolean = false,
// 浮窗的吸附方式(默认不吸附,拖到哪里是哪里)
var sidePattern: SidePattern = SidePattern.DEFAULT,
var sidePattern: SidePattern = SidePattern.DEFAULT,
// 浮窗显示类型(默认只在当前页显示)
var showPattern: ShowPattern = ShowPattern.CURRENT_ACTIVITY,
var showPattern: ShowPattern = ShowPattern.CURRENT_ACTIVITY,
// 倒计时关闭window-1 表示不自动关闭, 单位毫秒。1s = 1000ms
var countDownTime: Long = 0,
var countDownTime: Long = 0,
// 浮窗的摆放方式使用系统的Gravity属性
var gravity: Int = 0,
var gravity: Int = 0,
// 坐标的偏移量
var offsetPair: Pair<Int, Int> = Pair(0, 0),
var offsetPair: Pair<Int, Int> = Pair(0, 0),
// 固定的初始坐标,左上角坐标
var locationPair: Pair<Int, Int> = Pair(0, 0),
var locationPair: Pair<Int, Int> = Pair(0, 0),
// ps优先使用固定坐标若固定坐标不为原点坐标gravity属性和offset属性无效
// 四周边界值
var leftBorder: Int = 0,
var topBorder: Int = -999,
var rightBorder: Int = 9999,
var bottomBorder: Int = 9999,
var leftBorder: Int = 0,
var topBorder: Int = -999,
var rightBorder: Int = 9999,
var bottomBorder: Int = 9999,
// 出入动画
var floatAnimator: OnFloatAnimator? = DefaultAnimator(),
var floatAnimator: OnFloatAnimator? = DefaultAnimator(),
// 设置视图状态监听showdismiss
var statusListenerMapIMoGo: ArrayList< IMoGoWarningStatusListener> = ArrayList(),
var statusListenerMapIMoGo: ArrayList< IMoGoWarningStatusListener> = ArrayList(),
// Callbacks
var callbacks: OnFloatCallbacks? = null,
var callbacks: OnFloatCallbacks? = null,
// 窗口宽度
var width: Int = WindowManager.LayoutParams.WRAP_CONTENT,
var width: Int = WindowManager.LayoutParams.WRAP_CONTENT,
// 窗口高度
var height: Int = WindowManager.LayoutParams.WRAP_CONTENT
var height: Int = WindowManager.LayoutParams.WRAP_CONTENT
) {
var isEnqueue: Boolean = false
var isOverride: Boolean = true

View File

@@ -5,7 +5,7 @@ import android.animation.ValueAnimator
import android.graphics.Rect
import android.view.View
import android.view.WindowManager
import com.mogo.eagle.core.function.hmi.notification.enums.SidePattern
import com.mogo.eagle.core.data.enums.SidePattern
import com.mogo.eagle.core.function.hmi.notification.interfaces.OnFloatAnimator
import com.mogo.eagle.core.utilcode.util.WindowUtils
import kotlin.math.min
@@ -32,11 +32,11 @@ open class DefaultAnimator : OnFloatAnimator {
): Animator? = getAnimator(view, params, windowManager, sidePattern, true)
private fun getAnimator(
view: View,
params: WindowManager.LayoutParams,
windowManager: WindowManager,
sidePattern: SidePattern,
isExit: Boolean
view: View,
params: WindowManager.LayoutParams,
windowManager: WindowManager,
sidePattern: SidePattern,
isExit: Boolean
): Animator {
val triple = initValue(view, params, windowManager, sidePattern)
// 退出动画的起始值、终点值,与入场动画相反

View File

@@ -1,12 +0,0 @@
package com.mogo.eagle.core.function.hmi.notification.enums
/**
* @author: donghongyu
* @function: 浮窗显示类别
* @date: 2019-07-08 17:05
*/
enum class ShowPattern {
// 只在当前Activity显示、仅应用前台时显示、仅应用后台时显示一直显示不分前后台
CURRENT_ACTIVITY, FOREGROUND, BACKGROUND, ALL_TIME
}

View File

@@ -1,20 +0,0 @@
package com.mogo.eagle.core.function.hmi.notification.enums
/**
* @author: donghongyu
* @function: 浮窗的贴边模式
* @date: 2019-07-01 17:34
*/
enum class SidePattern {
// 默认不贴边,跟随手指移动
DEFAULT,
// 左、右、上、下四个方向固定(一直吸附在该方向边缘,只能在该方向的边缘移动)
LEFT, RIGHT, TOP, BOTTOM,
// 根据手指到屏幕边缘的距离,自动选择水平方向的贴边、垂直方向的贴边、四周方向的贴边
AUTO_HORIZONTAL, AUTO_VERTICAL, AUTO_SIDE,
// 拖拽时跟随手指移动,结束时贴边
RESULT_LEFT, RESULT_RIGHT, RESULT_TOP, RESULT_BOTTOM,
RESULT_HORIZONTAL, RESULT_VERTICAL, RESULT_SIDE
}

View File

@@ -3,7 +3,7 @@ package com.mogo.eagle.core.function.hmi.notification.interfaces
import android.animation.Animator
import android.view.View
import android.view.WindowManager
import com.mogo.eagle.core.function.hmi.notification.enums.SidePattern
import com.mogo.eagle.core.data.enums.SidePattern
/**
* @author: donghongyu

View File

@@ -15,12 +15,14 @@ import com.mogo.eagle.core.data.autopilot.AdUpgradeStateHelper
import com.mogo.eagle.core.data.camera.CameraEntity
import com.mogo.eagle.core.data.config.HmiBuildConfig
import com.mogo.eagle.core.data.constants.MoGoFragmentPaths
import com.mogo.eagle.core.data.enums.SidePattern
import com.mogo.eagle.core.data.enums.WarningDirectionEnum
import com.mogo.eagle.core.data.notice.NoticeNormalData
import com.mogo.eagle.core.data.notice.NoticeTrafficStylePushData
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.api.hmi.IMoGoHmiViewProxy
import com.mogo.eagle.core.function.api.hmi.view.IViewLimitingVelocity
import com.mogo.eagle.core.function.api.hmi.view.IViewNotification
import com.mogo.eagle.core.function.api.hmi.view.IViewTrafficLight
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWaringProvider
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
@@ -33,7 +35,6 @@ import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.function.hmi.WaringConst
import com.mogo.eagle.core.function.hmi.notification.WarningFloat
import com.mogo.eagle.core.function.hmi.notification.anim.DefaultAnimator
import com.mogo.eagle.core.function.hmi.notification.enums.SidePattern
import com.mogo.eagle.core.function.hmi.ui.camera.CameraListView
import com.mogo.eagle.core.function.hmi.ui.notice.NoticeBannerView
import com.mogo.eagle.core.function.hmi.ui.notice.NoticeNormalBannerView
@@ -91,6 +92,8 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
private var mViewTrafficLight: IViewTrafficLight? = null
// 限速 View代理
private var mViewLimitingVelocity: IViewLimitingVelocity? = null
// V2X预警弹窗 View 代理
private var mViewNotification: IViewNotification? = null
override fun vipIdentification(visible: Boolean) {
@@ -140,7 +143,8 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
// 首次初始化使用默认视图
setProxyTrafficLightView(viewTrafficLightVr)
setLimitingSpeedView(viewLimitingVelocity)
setProxyLimitingSpeedView(viewLimitingVelocity)
setProxyNotificationView(V2XNotificationView(view.context))
}
@OptIn(ExperimentalCoroutinesApi::class)
@@ -188,11 +192,15 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
}
}
override fun setProxyNotificationView(view: IViewNotification) {
mViewNotification = view
}
override fun setProxyTrafficLightView(view: IViewTrafficLight) {
mViewTrafficLight = view
}
override fun setLimitingSpeedView(view: IViewLimitingVelocity) {
override fun setProxyLimitingSpeedView(view: IViewLimitingVelocity) {
mViewLimitingVelocity = view
}
@@ -291,17 +299,11 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
setToolsViewVisibility(View.GONE)
}
// 控制 BadCase 按钮展示
if (HmiBuildConfig.isShowBadCaseView) {
CallerDevaToolsManager.initBadCase(vsBadCaseToolsView)
}
// 控制 限速UI 展示
if (HmiBuildConfig.isShowLimitingVelocityView) {
showLimitingVelocity(View.VISIBLE)
} else {
showLimitingVelocity(View.GONE)
}
// 控制 红绿灯 展示
if (HmiBuildConfig.isShowTrafficLightView) {
setTrafficLightVrVisibility(View.VISIBLE)
@@ -309,7 +311,7 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
setTrafficLightVrVisibility(View.GONE)
}
// 控制 切换视角 展示
// 控制 远程摄像头图标 展示
if (HmiBuildConfig.isShowCameraView) {
setCameraViewVisibility(View.VISIBLE)
} else {
@@ -422,63 +424,65 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
val floatWindow = mWarningFloat
val showTag = floatWindow?.config?.floatTag
if (floatWindow == null || TextUtils.isEmpty(showTag) || !floatWindow.isShow() || floatWindow.config.floatTag != tag) {
val notificationView = V2XNotificationView(it)
notificationView.setWarningIcon(EventTypeEnum.getWarningIcon(v2xType.toString()))
val warningContent = alertContent
?: EventTypeEnum.getWarningContent(v2xType.toString())
if (warningContent.isEmpty()) {
CallerLogger.e("$M_HMI$TAG", "Show warningContent is null or empty!")
return@launchWhenResumed
} else {
notificationView.setWarningContent(warningContent)
}
if (floatWindow != null && floatWindow.isShow()) {
WarningFloat.dismiss(floatWindow.config.floatTag, true)
}
mWarningFloat = WarningFloat.with(it)
.setTag(tag)
.setLayout(notificationView)
.setSidePattern(SidePattern.RESULT_TOP)
.setCountDownTime(expireTime)
.setGravity(Gravity.CENTER_HORIZONTAL, offsetY = 110)
.setImmersionStatusBar(true)
.isEnqueue(true)
.addWarningStatusListener(listenerIMoGo)
.addWarningStatusListener(object : IMoGoWarningStatusListener {
override fun onShow() {
// 创建弹窗成功才进行TTS播报
CallerLogger.d(
"$M_HMI$TAG",
"mWarningFloat = $mWarningFloat---ttsContent = $ttsContent"
)
if (mWarningFloat != null && !TextUtils.isEmpty(ttsContent) && playTts) {
CallerLogger.d("$M_HMI$TAG", "---> ttsContent = $ttsContent")
AIAssist.getInstance(activity)
.speakTTSVoice(ttsContent)
}
}
})
.setAnimator(object : DefaultAnimator() {
override fun enterAnim(
view: View,
params: WindowManager.LayoutParams,
windowManager: WindowManager,
sidePattern: SidePattern
): Animator? =
super.enterAnim(view, params, windowManager, sidePattern)?.apply {
interpolator = OvershootInterpolator()
}
// 代理View初始化了才可以弹窗
mViewNotification?.let { notificationView->
notificationView.setWarningIcon(EventTypeEnum.getWarningIcon(v2xType.toString()))
val warningContent = alertContent
?: EventTypeEnum.getWarningContent(v2xType.toString())
if (warningContent.isEmpty()) {
CallerLogger.e("$M_HMI$TAG", "Show warningContent is null or empty!")
return@launchWhenResumed
} else {
notificationView.setWarningContent(warningContent)
}
if (floatWindow != null && floatWindow.isShow()) {
WarningFloat.dismiss(floatWindow.config.floatTag, true)
}
mWarningFloat = WarningFloat.with(it)
.setTag(tag)
.setLayout(notificationView)
.setSidePattern(notificationView.sidePattern)
.setCountDownTime(expireTime)
.setGravity(notificationView.layoutGravity, offsetX = notificationView.offsetX, offsetY = notificationView.offsetY)
.setImmersionStatusBar(true)
.isEnqueue(true)
.addWarningStatusListener(listenerIMoGo)
.addWarningStatusListener(object : IMoGoWarningStatusListener {
override fun onShow() {
// 创建弹窗成功才进行TTS播报
CallerLogger.d(
"$M_HMI$TAG",
"mWarningFloat = $mWarningFloat---ttsContent = $ttsContent"
)
if (mWarningFloat != null && !TextUtils.isEmpty(ttsContent) && playTts) {
CallerLogger.d("$M_HMI$TAG", "---> ttsContent = $ttsContent")
AIAssist.getInstance(activity)
.speakTTSVoice(ttsContent)
}
}
})
.setAnimator(object : DefaultAnimator() {
override fun enterAnim(
view: View,
params: WindowManager.LayoutParams,
windowManager: WindowManager,
sidePattern: SidePattern
): Animator? =
super.enterAnim(view, params, windowManager, sidePattern)?.apply {
interpolator = OvershootInterpolator()
}
override fun exitAnim(
view: View,
params: WindowManager.LayoutParams,
windowManager: WindowManager,
sidePattern: SidePattern
): Animator? =
super.exitAnim(view, params, windowManager, sidePattern)
?.setDuration(200)
})
.show()
override fun exitAnim(
view: View,
params: WindowManager.LayoutParams,
windowManager: WindowManager,
sidePattern: SidePattern
): Animator? =
super.exitAnim(view, params, windowManager, sidePattern)
?.setDuration(200)
})
.show()
}
} else {
val notification = floatWindow.config.layoutView as? V2XNotificationView
if (alertContent?.isNotEmpty() == true) {
@@ -545,12 +549,17 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
* 控制展示限速标志及内容
*/
override fun showLimitingVelocity(limitingSpeed: Int) {
if (limitingSpeed > 0) {
mViewLimitingVelocity?.visibility = View.VISIBLE
mViewLimitingVelocity?.updateLimitingSpeed(limitingSpeed)
// 控制 限速UI 展示
if (HmiBuildConfig.isShowLimitingVelocityView) {
if (limitingSpeed > 0) {
mViewLimitingVelocity?.visibility = View.VISIBLE
mViewLimitingVelocity?.updateLimitingSpeed(limitingSpeed)
} else {
mViewLimitingVelocity?.visibility = View.INVISIBLE
mViewLimitingVelocity?.updateLimitingSpeed(0)
}
} else {
mViewLimitingVelocity?.visibility = View.INVISIBLE
mViewLimitingVelocity?.updateLimitingSpeed(0)
disableLimitingVelocity()
}
}

View File

@@ -15,7 +15,7 @@ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.function.hmi.notification.WarningFloat
import com.mogo.eagle.core.function.hmi.notification.anim.DefaultAnimator
import com.mogo.eagle.core.function.hmi.notification.enums.SidePattern
import com.mogo.eagle.core.data.enums.SidePattern
import com.mogo.usbcamera.UVCCameraHelper
import com.serenegiant.usb.ParentPreviewConstraintLayout
import com.serenegiant.usb.widget.CameraViewInterface

View File

@@ -3,49 +3,58 @@ package com.mogo.eagle.core.function.hmi.ui.widget
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.Gravity
import android.view.LayoutInflater
import androidx.annotation.DrawableRes
import androidx.annotation.Nullable
import androidx.annotation.StringRes
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.eagle.core.data.enums.SidePattern
import com.mogo.eagle.core.function.api.hmi.view.IViewNotification
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import kotlinx.android.synthetic.main.notification_v2x_msg_vr.view.*
/**
* 默认预警弹窗实现
*@author xiaoyuzhou
*@date 2021/8/6 12:25 下午
*/
class V2XNotificationView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : IViewNotification(context, attrs, defStyleAttr) {
init {
LayoutInflater.from(context).inflate(R.layout.notification_v2x_msg_vr, this, true)
// 设置View的出场位置
sidePattern = SidePattern.RESULT_TOP
layoutGravity = Gravity.CENTER_HORIZONTAL
// 设置View的停留位置
offsetX = 0
offsetY = 110
}
fun setWarningIcon(@DrawableRes warningIcon: Int) {
override fun setWarningIcon(@DrawableRes warningIcon: Int) {
UiThreadHandler.post {
ivWaringIcon.setImageResource(warningIcon)
}
}
fun setWarningIcon(@Nullable drawable: Drawable) {
override fun setWarningIcon(@Nullable drawable: Drawable) {
UiThreadHandler.post {
ivWaringIcon.setImageDrawable(drawable)
}
}
fun setWarningContent(@Nullable warningContent: CharSequence) {
override fun setWarningContent(@Nullable warningContent: CharSequence) {
UiThreadHandler.post {
tvWaringContent.text = warningContent
}
}
fun setWarningContent(@StringRes warningContentId: Int) {
override fun setWarningContent(@StringRes warningContentId: Int) {
UiThreadHandler.post {
tvWaringContent.setText(warningContentId)
}