[feedback]优化弹窗实现细节
This commit is contained in:
@@ -5,6 +5,7 @@ import android.transition.TransitionManager
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.Lifecycle.Event
|
||||
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
@@ -13,19 +14,20 @@ import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
|
||||
import com.mogo.eagle.core.utilcode.kotlin.PX
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.eagle.core.utilcode.kotlin.lifecycleOwner
|
||||
import com.mogo.eagle.core.utilcode.kotlin.onClick
|
||||
import com.mogo.eagle.core.utilcode.util.Utils
|
||||
import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason
|
||||
import com.zhjt.mogo_core_function_devatools.badcase.biz.BadCasePresenter
|
||||
import com.zhjt.mogo_core_function_devatools.badcase.biz.BadCaseView
|
||||
import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
|
||||
import com.zhjt.mogo_core_function_devatools.ext.pop
|
||||
import com.zhjt.mogo_core_function_devatools.ext.toast
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import record_cache.RecordPanelOuterClass
|
||||
import java.lang.IllegalStateException
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@@ -247,13 +249,10 @@ internal object BadCaseManager : LifecycleEventObserver {
|
||||
}
|
||||
|
||||
private fun showBadCaseFloat(onDismiss: () -> Unit, onSelect:suspend (reason: Reason) -> Unit) {
|
||||
val context = viewHolder?.get()?.context ?: Utils.getApp()
|
||||
BadCaseView(context).also { itx ->
|
||||
val activity = viewHolder?.get()?.context as? FragmentActivity ?: throw IllegalStateException("please ensure context is FragmentActivity.")
|
||||
BadCaseView(activity).also { itx ->
|
||||
itx.register(record, onDismiss, onSelect)
|
||||
CallerHmiManager.showFloatWindow("BadCaseFloat", floatView = itx, WindowManager.LayoutParams().also {
|
||||
it.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
|
||||
}
|
||||
).also {
|
||||
activity.pop(itx, 960.PX, WindowManager.LayoutParams.MATCH_PARENT).also {
|
||||
hideFloat = it
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,10 +58,10 @@ internal class BadCaseView: ConstraintLayout {
|
||||
LayoutInflater.from(context).inflate(R.layout.layout_badcase_collect, this, true)
|
||||
background = ColorDrawable(Color.parseColor("#F0151D41"))
|
||||
isClickable = true
|
||||
layoutParams = ViewGroup.LayoutParams(960.PX, 1600.PX)
|
||||
close?.onClick {
|
||||
onDismiss?.invoke()
|
||||
}
|
||||
fitsSystemWindows = true
|
||||
cancel?.also {
|
||||
it.background = shape(solid = Color.parseColor("#3B4577"), radius = 16)
|
||||
it.onClick {
|
||||
|
||||
@@ -99,7 +99,9 @@ internal object BadCaseStore {
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
suspend fun records(isDriven: Boolean): List<Reason> {
|
||||
CallerLogger.d("$M_DEVA${BadCaseManager.TAG}", "-- load cases from pb -- isDriven: $isDriven")
|
||||
val causes = store.data.firstOrNull()
|
||||
CallerLogger.d("$M_DEVA${BadCaseManager.TAG}", "-- load cases from pb -- result: $causes")
|
||||
val list = if (isDriven) causes?.drivenDataList else causes?.drivingDataList
|
||||
return list?.map {
|
||||
Reason().also { itx ->
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
package com.zhjt.mogo_core_function_devatools.ext
|
||||
|
||||
import android.R.id
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Build.VERSION
|
||||
import android.os.Build.VERSION_CODES
|
||||
import android.transition.Slide
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewTreeObserver
|
||||
import android.view.*
|
||||
import android.view.WindowManager.LayoutParams
|
||||
import android.view.animation.OvershootInterpolator
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.PopupWindow.INPUT_METHOD_NEEDED
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
@@ -20,10 +25,12 @@ import com.mogo.eagle.core.utilcode.kotlin.lifeCycleScope
|
||||
import com.mogo.eagle.core.utilcode.kotlin.shape
|
||||
import com.mogo.eagle.core.utilcode.reminder.Reminder
|
||||
import com.mogo.eagle.core.utilcode.reminder.api.impl.PopupWindowReminder
|
||||
import com.mogo.eagle.core.utilcode.util.WindowUtils
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeUnit.SECONDS
|
||||
import kotlin.math.abs
|
||||
|
||||
|
||||
/**
|
||||
@@ -58,6 +65,72 @@ internal fun Context.toast(text: CharSequence, duration: Long = 2, unit: TimeUni
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
internal fun Context.pop(content: View, width: Int, height: Int, fitSystemWindow: Boolean = true, onOuterViewClicked:((focus: View) -> Unit)? = null): () -> Unit {
|
||||
val activity = (this as? FragmentActivity) ?: throw IllegalStateException("please use Activity to trigger pop show.")
|
||||
var tempReminder: PopupWindowReminder? = null
|
||||
activity.lifecycleScope.launchWhenResumed {
|
||||
val pop = PopupWindow(width, height).also {
|
||||
it.isOutsideTouchable = true
|
||||
it.isTouchable = true
|
||||
it.isFocusable = true
|
||||
it.inputMethodMode = INPUT_METHOD_NEEDED
|
||||
it.isClippingEnabled = false
|
||||
var startX = 0f
|
||||
var startY = 0f
|
||||
val touchSlop = ViewConfiguration.get(activity).scaledTouchSlop
|
||||
var isClicked = false
|
||||
it.setTouchInterceptor { v, event ->
|
||||
val out = Rect()
|
||||
v.getGlobalVisibleRect(out)
|
||||
if (out.contains(event.x.toInt(), event.y.toInt())) {
|
||||
return@setTouchInterceptor false
|
||||
}
|
||||
|
||||
when(event.actionMasked) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
startX = event.x
|
||||
startY = event.y
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
val deltaX = event.x - startX
|
||||
val deltaY = event.y - startY
|
||||
isClicked = !(abs(deltaX) > touchSlop || abs(deltaY) > touchSlop)
|
||||
}
|
||||
MotionEvent.ACTION_UP -> {
|
||||
if (isClicked) {
|
||||
isClicked = false
|
||||
onOuterViewClicked?.invoke(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return@setTouchInterceptor true
|
||||
}
|
||||
it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
}
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.M) {
|
||||
val transition = Slide(Gravity.START).also {
|
||||
it.interpolator = OvershootInterpolator()
|
||||
it.duration = 300
|
||||
}
|
||||
pop.enterTransition = transition
|
||||
pop.exitTransition = transition
|
||||
}
|
||||
pop.contentView = content
|
||||
val reminder = object : PopupWindowReminder(pop) {
|
||||
override fun show() {
|
||||
pop.showAtLocation(activity.window.decorView, Gravity.START, 0, if (fitSystemWindow) WindowUtils.getStatusBarHeight(activity) else 0)
|
||||
}
|
||||
override fun isOverride(): Boolean = true
|
||||
}
|
||||
tempReminder = reminder
|
||||
Reminder.enqueue(activity.lifeCycleOwner, reminder)
|
||||
}
|
||||
return {
|
||||
tempReminder?.hide()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun FragmentActivity.softKeyboardHeightChanged(block: ((height: Int) -> Unit)): ()-> Unit {
|
||||
val decor = window.decorView
|
||||
var softKeyboardDisplayed = false
|
||||
@@ -115,3 +188,5 @@ private fun getNavigationBarHeight(activity: FragmentActivity): Int {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,21 +3,24 @@ package com.zhjt.mogo_core_function_devatools.feedback
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
|
||||
import com.mogo.eagle.core.utilcode.kotlin.*
|
||||
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast
|
||||
import com.mogo.eagle.core.utilcode.util.KeyboardUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.zhjt.mogo_core_function_devatools.R
|
||||
import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
|
||||
import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason
|
||||
import com.zhjt.mogo_core_function_devatools.badcase.toRecord
|
||||
import com.zhjt.mogo_core_function_devatools.ext.pop
|
||||
import com.zhjt.mogo_core_function_devatools.ext.toast
|
||||
import com.zhjt.mogo_core_function_devatools.feedback.biz.FeedBackView
|
||||
import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback.BadCase
|
||||
@@ -35,9 +38,11 @@ internal object FeedbackManager {
|
||||
private val presenter by lazy { FeedbackPresenter() }
|
||||
|
||||
fun showFeedbackWindow(ctx: Context) {
|
||||
CallerHmiManager.showFloatWindow("Feedback", FeedBackView(ctx).also { itx ->
|
||||
val activity = ctx as? FragmentActivity ?: throw IllegalStateException("please ensure context is FragmentActivity.")
|
||||
activity.pop(FeedBackView(ctx).also { itx ->
|
||||
itx.registerCallback(object : IFeedbackCallback {
|
||||
override fun onClose() {
|
||||
override fun onClose(v: View) {
|
||||
KeyboardUtils.hideSoftInput(v)
|
||||
hideFloat?.invoke()
|
||||
}
|
||||
override fun onBadCaseItemClicked(reason: Reason) {
|
||||
@@ -139,9 +144,12 @@ internal object FeedbackManager {
|
||||
}
|
||||
}
|
||||
})
|
||||
}, WindowManager.LayoutParams().also {
|
||||
it.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
|
||||
}
|
||||
},
|
||||
width = 960.PX,
|
||||
height = WindowManager.LayoutParams.MATCH_PARENT,
|
||||
onOuterViewClicked = {
|
||||
KeyboardUtils.hideSoftInput(it)
|
||||
}
|
||||
).also { hideFloat = it }
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,10 @@ import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.mogo.eagle.core.utilcode.kotlin.*
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA
|
||||
import com.zhjt.mogo_core_function_devatools.R
|
||||
import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager
|
||||
import com.zhjt.mogo_core_function_devatools.ext.softKeyboardHeightChanged
|
||||
import com.zhjt.mogo_core_function_devatools.feedback.FeedbackManager
|
||||
import com.zhjt.mogo_core_function_devatools.feedback.biz.adapter.FeedbackAdapter
|
||||
@@ -68,13 +71,12 @@ internal class FeedBackView : ConstraintLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
layoutParams = ViewGroup.LayoutParams(960.PX, 1600.PX)
|
||||
background = ColorDrawable(Color.parseColor("#F0151D41"))
|
||||
close.onClick {
|
||||
cb?.onClose()
|
||||
cb?.onClose(this)
|
||||
}
|
||||
|
||||
top_mask?.background = gradient(orientation = GradientDrawable.Orientation.TOP_BOTTOM, startColor = Color.parseColor("#151D41"), endColor = Color.parseColor("#05151D41"))
|
||||
background = ColorDrawable(Color.parseColor("#F0151D41"))
|
||||
rv?.also {
|
||||
it.fixGestureConflictForViews(listOf(R.id.et))
|
||||
it.itemAnimator?.run {
|
||||
@@ -116,9 +118,12 @@ internal class FeedBackView : ConstraintLayout {
|
||||
private fun loadFeedbackAndRefresh() {
|
||||
scope.launchWhenCreated {
|
||||
showLoading()
|
||||
CallerLogger.d("$M_DEVA${BadCaseManager.TAG}", "-- show loading ---")
|
||||
presenter.loadFeedBacks().also {
|
||||
CallerLogger.d("$M_DEVA${BadCaseManager.TAG}", "-- data load ${it.joinToString(",")} ---")
|
||||
adapter.data = it
|
||||
}
|
||||
CallerLogger.d("$M_DEVA${BadCaseManager.TAG}", "-- hide loading ---")
|
||||
hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ internal interface IFeedbackCallback {
|
||||
/**
|
||||
* 点击关闭弹窗按钮时回调
|
||||
*/
|
||||
fun onClose()
|
||||
fun onClose(v: View)
|
||||
|
||||
/**
|
||||
* BadCase某一条目被点击了
|
||||
|
||||
@@ -907,60 +907,8 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
|
||||
}
|
||||
|
||||
override fun showFloatWindow(tag: String, floatView: View, attrs: LayoutParams?): () -> Unit {
|
||||
var floatWindow: WarningFloat.Builder?
|
||||
WarningFloat.with(context ?: Utils.getApp())
|
||||
.setTag(tag)
|
||||
.setLayout(floatView)
|
||||
.setSidePattern(SidePattern.LEFT)
|
||||
.setGravity(Gravity.START, offsetY = 72)
|
||||
.setImmersionStatusBar(true)
|
||||
.setAnimator(object : DefaultAnimator() {
|
||||
override fun enterAnim(
|
||||
view: View,
|
||||
params: LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.enterAnim(view, params, windowManager, sidePattern)
|
||||
?.apply {
|
||||
interpolator = OvershootInterpolator()
|
||||
}
|
||||
|
||||
override fun exitAnim(
|
||||
view: View,
|
||||
params: LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.exitAnim(view, params, windowManager, sidePattern)
|
||||
?.setDuration(200)
|
||||
})
|
||||
.addWarningStatusListener(object : IMoGoWarningStatusListener {
|
||||
override fun onDismiss() {
|
||||
floatWindow = null
|
||||
}
|
||||
})
|
||||
.also {
|
||||
floatWindow = it
|
||||
if (((attrs?.softInputMode?: 0) and LayoutParams.SOFT_INPUT_MASK_ADJUST) != 0) {
|
||||
it.softInputMode(attrs!!.softInputMode)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
return {
|
||||
floatWindow?.let {
|
||||
WarningFloat.dismiss(it.config.floatTag, false)
|
||||
floatWindow = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
CallerLogger.d("$M_HMI$TAG", "onDestroy")
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -217,13 +217,4 @@ interface IMoGoWaringProvider : IMoGoHmiViewProxy {
|
||||
* @param msg
|
||||
*/
|
||||
fun showDockerRebootResult(code: Int,msg: String)
|
||||
|
||||
/**
|
||||
* @param floatView: 要展示的View
|
||||
* @param tag: 唯一标识
|
||||
* @return 触发消失时回调
|
||||
*/
|
||||
fun showFloatWindow(tag: String = "BadCaseFloat", floatView: View, attrs: LayoutParams?): () -> Unit
|
||||
|
||||
|
||||
}
|
||||
@@ -297,13 +297,6 @@ object CallerHmiManager : CallerBase() {
|
||||
waringProviderApi?.showDockerRebootResult(code, msg)
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示浮层
|
||||
*/
|
||||
fun showFloatWindow(tag: String, floatView: View, attrs: LayoutParams? = null): (() -> Unit)? {
|
||||
return waringProviderApi?.showFloatWindow(tag, floatView, attrs)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 红绿灯 代理View
|
||||
* @param view
|
||||
|
||||
Reference in New Issue
Block a user