refactor: 优化 QuTipDialog + 删除 ResultFlashView
QuTipDialog 优化: - 图标区域放大 85→110dp,图标字号 38→50sp - 加入淡入+缩放动画(OvershootInterpolator 回弹效果) - 默认倒计时 3→2 秒 - 倒计时文字默认隐藏(showCountdown 参数控制) - 简化调用:show(status, title) 即可,2秒后自动消失 NFC 打卡加回 QuTipDialog: - 成功:绿色图标 + "打卡成功" + 2秒消失 - 失败:红色图标 + "打卡失败" + 错误信息 删除 ResultFlashView(方案不合适,统一用优化后的 QuTipDialog) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,6 @@ import com.xiaoqu.watch.service.manager.NfcTaskManager
|
|||||||
import com.xiaoqu.watch.service.manager.NotificationManager
|
import com.xiaoqu.watch.service.manager.NotificationManager
|
||||||
import com.xiaoqu.watch.service.manager.SystemStateMonitor
|
import com.xiaoqu.watch.service.manager.SystemStateMonitor
|
||||||
import com.xiaoqu.watch.service.manager.UpdateManager
|
import com.xiaoqu.watch.service.manager.UpdateManager
|
||||||
import com.xiaoqu.watch.ui.widget.ResultFlashView
|
|
||||||
import com.xiaoqu.watch.ui.widget.UpdateDialogView
|
import com.xiaoqu.watch.ui.widget.UpdateDialogView
|
||||||
import com.xiaoqu.watch.ui.widget.NotificationBannerView
|
import com.xiaoqu.watch.ui.widget.NotificationBannerView
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@@ -51,8 +50,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
/** NFC 任务打卡管理器 */
|
/** NFC 任务打卡管理器 */
|
||||||
@Inject lateinit var nfcTaskManager: NfcTaskManager
|
@Inject lateinit var nfcTaskManager: NfcTaskManager
|
||||||
@Inject lateinit var userPrefs: UserPrefs
|
@Inject lateinit var userPrefs: UserPrefs
|
||||||
/** 操作结果指示器(Apple Watch 风格) */
|
|
||||||
lateinit var resultFlash: ResultFlashView
|
|
||||||
/** OTA 更新弹窗 */
|
/** OTA 更新弹窗 */
|
||||||
lateinit var updateDialog: UpdateDialogView
|
lateinit var updateDialog: UpdateDialogView
|
||||||
lateinit var notificationBanner: NotificationBannerView
|
lateinit var notificationBanner: NotificationBannerView
|
||||||
@@ -88,9 +85,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
// 初始化通知横幅
|
// 初始化通知横幅
|
||||||
notificationBanner = binding.notificationBanner
|
notificationBanner = binding.notificationBanner
|
||||||
|
|
||||||
// 初始化结果指示器
|
|
||||||
resultFlash = binding.resultFlash
|
|
||||||
|
|
||||||
// 初始化 OTA 更新弹窗
|
// 初始化 OTA 更新弹窗
|
||||||
updateDialog = binding.updateDialog
|
updateDialog = binding.updateDialog
|
||||||
setupUpdateDialog()
|
setupUpdateDialog()
|
||||||
@@ -211,10 +205,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
Timber.d("返回键: 触发主动打卡")
|
Timber.d("返回键: 触发主动打卡")
|
||||||
nfcTaskManager.startActivePunch { success, message ->
|
nfcTaskManager.startActivePunch { success, message ->
|
||||||
if (success) {
|
if (message.isNotEmpty()) {
|
||||||
resultFlash.showSuccess()
|
android.widget.Toast.makeText(this@MainActivity, message, android.widget.Toast.LENGTH_SHORT).show()
|
||||||
} else if (message.isNotEmpty()) {
|
|
||||||
resultFlash.showFailure()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,12 +222,20 @@ class TaskDetailFragment : BaseFragment<FragmentTaskDetailBinding>() {
|
|||||||
btn.setBackgroundResource(R.drawable.bg_foot_btn_grey)
|
btn.setBackgroundResource(R.drawable.bg_foot_btn_grey)
|
||||||
|
|
||||||
nfcTaskManager.startTaskPunch(taskId) { success, message ->
|
nfcTaskManager.startTaskPunch(taskId) { success, message ->
|
||||||
val resultFlash = (activity as? com.xiaoqu.watch.app.MainActivity)?.resultFlash
|
|
||||||
if (success) {
|
if (success) {
|
||||||
resultFlash?.showSuccess { findNavController().popBackStack() }
|
tipDialog.show(
|
||||||
|
status = QuTipDialog.Status.SUCCESS,
|
||||||
|
title = "打卡成功",
|
||||||
|
step = 1,
|
||||||
|
onBack = { findNavController().popBackStack() }
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
if (message != "超时") {
|
if (message != "超时") {
|
||||||
resultFlash?.showFailure()
|
tipDialog.show(
|
||||||
|
status = QuTipDialog.Status.ERROR,
|
||||||
|
title = "打卡失败",
|
||||||
|
desc = message
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// 恢复按钮(可重试)
|
// 恢复按钮(可重试)
|
||||||
btn.text = "开启打卡"
|
btn.text = "开启打卡"
|
||||||
|
|||||||
@@ -451,12 +451,20 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
|
|||||||
btn.setBackgroundResource(R.drawable.bg_foot_btn_grey)
|
btn.setBackgroundResource(R.drawable.bg_foot_btn_grey)
|
||||||
|
|
||||||
nfcTaskManager.startTaskPunch(taskId) { success, message ->
|
nfcTaskManager.startTaskPunch(taskId) { success, message ->
|
||||||
val resultFlash = (activity as? com.xiaoqu.watch.app.MainActivity)?.resultFlash
|
|
||||||
if (success) {
|
if (success) {
|
||||||
resultFlash?.showSuccess { fetchCurrentDetail() }
|
tipDialog.show(
|
||||||
|
status = QuTipDialog.Status.SUCCESS,
|
||||||
|
title = "打卡成功"
|
||||||
|
)
|
||||||
|
// 2 秒后(弹窗消失后)刷新任务详情
|
||||||
|
btn.postDelayed({ fetchCurrentDetail() }, 2100)
|
||||||
} else {
|
} else {
|
||||||
if (message != "超时") {
|
if (message != "超时") {
|
||||||
resultFlash?.showFailure()
|
tipDialog.show(
|
||||||
|
status = QuTipDialog.Status.ERROR,
|
||||||
|
title = "打卡失败",
|
||||||
|
desc = message
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// 恢复按钮(可重试)
|
// 恢复按钮(可重试)
|
||||||
btn.text = "开启打卡"
|
btn.text = "开启打卡"
|
||||||
|
|||||||
@@ -1,30 +1,35 @@
|
|||||||
package com.xiaoqu.watch.ui.widget
|
package com.xiaoqu.watch.ui.widget
|
||||||
|
|
||||||
|
import android.animation.AnimatorSet
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.os.CountDownTimer
|
import android.os.CountDownTimer
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.animation.OvershootInterpolator
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.xiaoqu.watch.R
|
import com.xiaoqu.watch.R
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提示弹窗(对应旧版 qu-tip.vue)
|
* 提示弹窗(优化版)
|
||||||
* 显示状态图标(成功/警告/错误)+ 标题 + 可选描述 + 倒计时自动关闭/返回
|
*
|
||||||
|
* 显示状态图标(成功/警告/错误)+ 标题 + 可选描述
|
||||||
|
* 带淡入+缩放动画,自动倒计时关闭
|
||||||
*
|
*
|
||||||
* 使用方式:
|
* 使用方式:
|
||||||
* ```
|
* ```
|
||||||
* val tip = QuTipDialog(binding.dialogContainer)
|
* // 简洁模式:1.5 秒后自动消失
|
||||||
* tip.show(
|
* tip.show(status = SUCCESS, title = "打卡成功")
|
||||||
* status = QuTipDialog.Status.SUCCESS,
|
*
|
||||||
* title = "打卡成功",
|
* // 带返回:1.5 秒后自动消失并执行回调
|
||||||
* desc = "已记录考勤",
|
* tip.show(status = SUCCESS, title = "打卡成功",
|
||||||
* back = true,
|
* step = 1, onBack = { popBackStack() })
|
||||||
* step = 1, // 0=只关闭,1=返回上一页
|
*
|
||||||
* countdown = 3,
|
* // 带描述 + 倒计时文字
|
||||||
* onBack = { findMainNavController().popBackStack() }
|
* tip.show(status = ERROR, title = "打卡失败", desc = "网络异常",
|
||||||
* )
|
* showCountdown = true, countdown = 3)
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class QuTipDialog(
|
class QuTipDialog(
|
||||||
@@ -38,12 +43,13 @@ class QuTipDialog(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示提示弹窗
|
* 显示提示弹窗
|
||||||
* @param status 状态类型(成功/警告/错误/定位)
|
* @param status 状态类型
|
||||||
* @param title 标题文字
|
* @param title 标题文字
|
||||||
* @param desc 描述文字(可选)
|
* @param desc 描述文字(可选,不传则不显示)
|
||||||
* @param back 是否显示倒计时返回按钮
|
* @param back 是否自动倒计时关闭(默认 true)
|
||||||
* @param step 倒计时结束后行为:0=只关闭弹窗,>0=触发 onBack 回调
|
* @param step 倒计时结束后行为:0=只关闭,>0=触发 onBack 回调
|
||||||
* @param countdown 倒计时秒数(默认 3 秒)
|
* @param countdown 倒计时秒数(默认 2 秒)
|
||||||
|
* @param showCountdown 是否显示倒计时文字(默认 false,更简洁)
|
||||||
* @param onBack 返回回调(step > 0 时触发)
|
* @param onBack 返回回调(step > 0 时触发)
|
||||||
*/
|
*/
|
||||||
fun show(
|
fun show(
|
||||||
@@ -51,8 +57,9 @@ class QuTipDialog(
|
|||||||
title: String,
|
title: String,
|
||||||
desc: String? = null,
|
desc: String? = null,
|
||||||
back: Boolean = true,
|
back: Boolean = true,
|
||||||
step: Int = 1,
|
step: Int = 0,
|
||||||
countdown: Int = 3,
|
countdown: Int = 2,
|
||||||
|
showCountdown: Boolean = false,
|
||||||
onBack: (() -> Unit)? = null
|
onBack: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
// 先移除旧弹窗
|
// 先移除旧弹窗
|
||||||
@@ -103,29 +110,33 @@ class QuTipDialog(
|
|||||||
descView.visibility = View.VISIBLE
|
descView.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
// 倒计时返回按钮
|
// 倒计时
|
||||||
val backBtn = view.findViewById<TextView>(R.id.tipBackBtn)
|
val backBtn = view.findViewById<TextView>(R.id.tipBackBtn)
|
||||||
if (back) {
|
if (back) {
|
||||||
|
if (showCountdown) {
|
||||||
backBtn.visibility = View.VISIBLE
|
backBtn.visibility = View.VISIBLE
|
||||||
backBtn.typeface = typeface
|
backBtn.typeface = typeface
|
||||||
|
}
|
||||||
|
|
||||||
// 启动倒计时
|
// 启动倒计时
|
||||||
timer = object : CountDownTimer(countdown * 1000L, 1000L) {
|
timer = object : CountDownTimer(countdown * 1000L, 1000L) {
|
||||||
override fun onTick(millisUntilFinished: Long) {
|
override fun onTick(millisUntilFinished: Long) {
|
||||||
|
if (showCountdown) {
|
||||||
val seconds = (millisUntilFinished / 1000) + 1
|
val seconds = (millisUntilFinished / 1000) + 1
|
||||||
backBtn.text = "${IconFont.BACK} ${seconds}s"
|
backBtn.text = "${IconFont.BACK} ${seconds}s"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onFinish() {
|
override fun onFinish() {
|
||||||
dismiss()
|
dismiss()
|
||||||
// step > 0 时触发返回回调
|
|
||||||
if (step > 0) {
|
if (step > 0) {
|
||||||
onBack?.invoke()
|
onBack?.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.start()
|
}.start()
|
||||||
|
|
||||||
// 点击立即返回(不等倒计时)
|
// 点击立即关闭(不等倒计时)
|
||||||
|
if (showCountdown) {
|
||||||
backBtn.setOnClickListener {
|
backBtn.setOnClickListener {
|
||||||
dismiss()
|
dismiss()
|
||||||
if (step > 0) {
|
if (step > 0) {
|
||||||
@@ -133,10 +144,28 @@ class QuTipDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 显示弹窗
|
// 显示弹窗
|
||||||
container.addView(view)
|
container.addView(view)
|
||||||
container.visibility = View.VISIBLE
|
container.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
// 淡入 + 缩放动画
|
||||||
|
val content = view.findViewById<View>(R.id.tipContent)
|
||||||
|
content.alpha = 0f
|
||||||
|
content.scaleX = 0.8f
|
||||||
|
content.scaleY = 0.8f
|
||||||
|
|
||||||
|
val fadeIn = ObjectAnimator.ofFloat(content, "alpha", 0f, 1f)
|
||||||
|
val scaleX = ObjectAnimator.ofFloat(content, "scaleX", 0.8f, 1f)
|
||||||
|
val scaleY = ObjectAnimator.ofFloat(content, "scaleY", 0.8f, 1f)
|
||||||
|
|
||||||
|
AnimatorSet().apply {
|
||||||
|
playTogether(fadeIn, scaleX, scaleY)
|
||||||
|
duration = 250
|
||||||
|
interpolator = OvershootInterpolator(1.2f)
|
||||||
|
start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 关闭弹窗 */
|
/** 关闭弹窗 */
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
package com.xiaoqu.watch.ui.widget
|
|
||||||
|
|
||||||
import android.animation.AnimatorSet
|
|
||||||
import android.animation.ObjectAnimator
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.drawable.GradientDrawable
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.animation.OvershootInterpolator
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import android.widget.TextView
|
|
||||||
import com.xiaoqu.watch.R
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 操作结果闪烁指示器(Apple Watch 风格)
|
|
||||||
*
|
|
||||||
* 全屏深色遮罩 + 中心大圆圈图标,属性动画弹出后自动淡出。
|
|
||||||
* 用于所有操作的成功/失败反馈,替代 QuTipDialog。
|
|
||||||
*
|
|
||||||
* 使用方式:
|
|
||||||
* - 添加到 activity_main.xml 最顶层
|
|
||||||
* - 调用 showSuccess() 或 showFailure()
|
|
||||||
* - 1.5 秒后自动消失,执行 onDismiss 回调
|
|
||||||
*/
|
|
||||||
class ResultFlashView @JvmOverloads constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
defStyleAttr: Int = 0
|
|
||||||
) : FrameLayout(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
/** 弹出动画时长(毫秒) */
|
|
||||||
private const val ANIM_IN_DURATION = 300L
|
|
||||||
/** 停留时长(毫秒) */
|
|
||||||
private const val STAY_DURATION = 1000L
|
|
||||||
/** 淡出动画时长(毫秒) */
|
|
||||||
private const val ANIM_OUT_DURATION = 300L
|
|
||||||
/** 成功绿色 */
|
|
||||||
private const val COLOR_SUCCESS = 0xFF4CAF50.toInt()
|
|
||||||
/** 失败红色 */
|
|
||||||
private const val COLOR_FAILURE = 0xFFF44336.toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val iconContainer: View
|
|
||||||
private val circleRing: View
|
|
||||||
private val tvIcon: TextView
|
|
||||||
|
|
||||||
/** 消失后回调 */
|
|
||||||
var onDismiss: (() -> Unit)? = null
|
|
||||||
|
|
||||||
init {
|
|
||||||
LayoutInflater.from(context).inflate(R.layout.view_result_flash, this, true)
|
|
||||||
iconContainer = findViewById(R.id.iconContainer)
|
|
||||||
circleRing = findViewById(R.id.circleRing)
|
|
||||||
tvIcon = findViewById(R.id.tvIcon)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 显示成功指示器(绿色 ✓) */
|
|
||||||
fun showSuccess(onDone: (() -> Unit)? = null) {
|
|
||||||
onDismiss = onDone
|
|
||||||
setColor(COLOR_SUCCESS)
|
|
||||||
tvIcon.text = "✓"
|
|
||||||
playAnimation()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 显示失败指示器(红色 ✗) */
|
|
||||||
fun showFailure(onDone: (() -> Unit)? = null) {
|
|
||||||
onDismiss = onDone
|
|
||||||
setColor(COLOR_FAILURE)
|
|
||||||
tvIcon.text = "✗"
|
|
||||||
playAnimation()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 设置圆圈颜色 */
|
|
||||||
private fun setColor(color: Int) {
|
|
||||||
val drawable = circleRing.background as? GradientDrawable
|
|
||||||
drawable?.setStroke(6, color)
|
|
||||||
tvIcon.setTextColor(color)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 执行弹出 → 停留 → 淡出动画 */
|
|
||||||
private fun playAnimation() {
|
|
||||||
// 重置状态
|
|
||||||
visibility = View.VISIBLE
|
|
||||||
alpha = 1f
|
|
||||||
iconContainer.scaleX = 0.3f
|
|
||||||
iconContainer.scaleY = 0.3f
|
|
||||||
iconContainer.alpha = 0f
|
|
||||||
|
|
||||||
// 弹出动画(scale + alpha,OvershootInterpolator 有回弹效果)
|
|
||||||
val scaleX = ObjectAnimator.ofFloat(iconContainer, "scaleX", 0.3f, 1f)
|
|
||||||
val scaleY = ObjectAnimator.ofFloat(iconContainer, "scaleY", 0.3f, 1f)
|
|
||||||
val alphaIn = ObjectAnimator.ofFloat(iconContainer, "alpha", 0f, 1f)
|
|
||||||
|
|
||||||
val animIn = AnimatorSet().apply {
|
|
||||||
playTogether(scaleX, scaleY, alphaIn)
|
|
||||||
duration = ANIM_IN_DURATION
|
|
||||||
interpolator = OvershootInterpolator(1.5f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 淡出动画
|
|
||||||
val fadeOut = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f).apply {
|
|
||||||
duration = ANIM_OUT_DURATION
|
|
||||||
startDelay = ANIM_IN_DURATION + STAY_DURATION
|
|
||||||
}
|
|
||||||
|
|
||||||
// 播放
|
|
||||||
animIn.start()
|
|
||||||
fadeOut.start()
|
|
||||||
|
|
||||||
// 动画结束后隐藏 + 回调
|
|
||||||
postDelayed({
|
|
||||||
visibility = View.GONE
|
|
||||||
alpha = 1f
|
|
||||||
onDismiss?.invoke()
|
|
||||||
onDismiss = null
|
|
||||||
}, ANIM_IN_DURATION + STAY_DURATION + ANIM_OUT_DURATION)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 结果指示器圆形边框(默认绿色,代码中动态设置颜色) -->
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="oval">
|
|
||||||
<stroke android:width="4dp" android:color="#4CAF50" />
|
|
||||||
</shape>
|
|
||||||
@@ -33,14 +33,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<!-- Layer 4: 操作结果指示器(Apple Watch 风格,弹出+淡出,默认隐藏) -->
|
<!-- Layer 4: OTA 更新弹窗(最顶层,全屏覆盖,默认隐藏) -->
|
||||||
<com.xiaoqu.watch.ui.widget.ResultFlashView
|
|
||||||
android:id="@+id/resultFlash"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<!-- Layer 5: OTA 更新弹窗(最顶层,全屏覆盖,默认隐藏) -->
|
|
||||||
<com.xiaoqu.watch.ui.widget.UpdateDialogView
|
<com.xiaoqu.watch.ui.widget.UpdateDialogView
|
||||||
android:id="@+id/updateDialog"
|
android:id="@+id/updateDialog"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- QuTipDialog:反馈提示弹窗(按原型图V3样式)
|
<!-- QuTipDialog:反馈提示弹窗(优化版)
|
||||||
圆形图标背景 + 大标题 + 描述 + 倒计时 -->
|
大圆形图标 + 标题,简洁清晰 -->
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/background">
|
android:background="@color/background">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/tipContent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
@@ -14,11 +15,11 @@
|
|||||||
android:paddingStart="21dp"
|
android:paddingStart="21dp"
|
||||||
android:paddingEnd="21dp">
|
android:paddingEnd="21dp">
|
||||||
|
|
||||||
<!-- 圆形图标背景(85dp) -->
|
<!-- 圆形图标背景(放大 85→110dp) -->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="85dp"
|
android:layout_width="110dp"
|
||||||
android:layout_height="85dp"
|
android:layout_height="110dp"
|
||||||
android:layout_marginBottom="19dp">
|
android:layout_marginBottom="16dp">
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/tipIconBg"
|
android:id="@+id/tipIconBg"
|
||||||
@@ -30,7 +31,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="38sp" />
|
android:textSize="50sp" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@
|
|||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<!-- 描述(20sp) -->
|
<!-- 描述(20sp,可选) -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tipDesc"
|
android:id="@+id/tipDesc"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -55,7 +56,7 @@
|
|||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<!-- 倒计时 -->
|
<!-- 倒计时(隐藏,只在需要时显示) -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tipBackBtn"
|
android:id="@+id/tipBackBtn"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 操作结果闪烁指示器(类 Apple Watch 风格)
|
|
||||||
全屏深色遮罩 + 中心大图标,属性动画弹出/淡出 -->
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="#CC000000">
|
|
||||||
|
|
||||||
<!-- 中心图标容器(圆形背景 + 图标文字) -->
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/iconContainer"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="100dp"
|
|
||||||
android:layout_gravity="center">
|
|
||||||
|
|
||||||
<!-- 圆形边框 -->
|
|
||||||
<View
|
|
||||||
android:id="@+id/circleRing"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@drawable/bg_result_circle" />
|
|
||||||
|
|
||||||
<!-- ✓ 或 ✗ 图标 -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvIcon"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="48sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
Reference in New Issue
Block a user