首单半价对话框的实现

需求分析

我们需要实现一个"首单半价"对话框,具有以下特性:

  • 每次用户打开应用时自动显示

  • 用户在应用内跳转时不显示

  • 可以通过横幅按钮手动触发显示

  • 提供良好的视觉体验和动画效果

技术实现方案

1. 状态管理

kotlin
// 升级服务弹窗状态
var showUpgradePopup by remember { mutableStateOf(false) }

使用 Compose 的 remember 和 mutableStateOf 管理对话框的显示状态,确保状态在重组时保持一致性。

2. 应用启动检测机制

核心挑战在于区分应用启动和应用内跳转。我们采用了基于时间戳的应用启动检测方案:

kotlin
// 使用Application级别的SharedPreferences结合时间戳控制对话框显示
val sharedPreferences = remember { 
    context.applicationContext.getSharedPreferences("app_preferences", Context.MODE_PRIVATE)
}

// 每次屏幕组合时检查是否需要显示对话框
LaunchedEffect(Unit) {
    // 添加500ms延迟,确保页面加载完成后再显示弹窗
    delay(500)
    
    val currentTime = System.currentTimeMillis()
    val appLaunchTime = sharedPreferences.getLong("app_launch_time", 0)
    val launchThreshold = 180000 // 3分钟阈值,超过则认为是新的应用启动
    
    // 如果是首次启动或时间间隔超过阈值,显示对话框
    if (appLaunchTime == 0L || currentTime - appLaunchTime > launchThreshold) {
        showUpgradePopup = true
        // 只在首次启动时记录应用启动时间
        if (appLaunchTime == 0L) {
            sharedPreferences.edit { putLong("app_launch_time", currentTime) }
        }
    }
}

关键设计决策:

  1. 使用 Application Context:通过 context.applicationContext 获取应用级别的 SharedPreferences,确保数据在应用生命周期内持久化。

  2. 3分钟阈值策略:设置 180000 毫秒(3分钟)的时间阈值,区分真正的应用启动和应用内跳转。

  3. 延迟显示:添加 500ms 延迟,确保页面完全加载后再显示弹窗,避免页面闪烁。

  4. 一次性记录:只在首次启动时记录时间戳,避免重复触发。

3. 手动触发机制

除了自动显示,我们还需要提供手动触发的途径:

kotlin
// 点击升级服务按钮显示弹窗
val showUpgradePopupHandler: () -> Unit = {
    showUpgradePopup = true
}

// 在横幅中绑定点击事件
UpgradeServiceBanner(onClick = showUpgradePopupHandler)

4. 视觉实现

对话框采用 Material Design 3 的 AlertDialog,并添加了入场动画:

kotlin
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun UpgradeServicePopup(
    onDismiss: () -> Unit
) {
    AnimatedVisibility(
        visible = true,
        enter = fadeIn(animationSpec = tween(300)) + scaleIn(animationSpec = tween(300)),
        exit = fadeOut(animationSpec = tween(300)) + scaleOut(animationSpec = tween(300))
    ) {
        AlertDialog(
            onDismissRequest = onDismiss,
            title = {
                Text(
                    text = "首单半价",
                    fontSize = 20.sp,
                    fontWeight = FontWeight.Bold,
                    color = MaterialTheme.colorScheme.onSurface,
                    textAlign = TextAlign.Center
                )
            },
            // ... 其他配置
        )
    }
}

技术难点与解决方案

难点1:区分应用启动和应用内跳转

解决方案:采用时间戳阈值策略,将3分钟内的访问视为同一会话,3分钟后的访问视为新的应用启动。

难点2:避免页面加载过程中的视觉闪烁

解决方案:添加500ms延迟,确保页面布局完全稳定后再显示弹窗。

难点3:保持状态持久性

解决方案:使用应用级别的 SharedPreferences,确保数据在应用生命周期内持久保存。

总结

通过巧妙的時間戳策略和合理的用户体验设计,我们成功实现了"首单半价"对话框的智能显示机制。这个解决方案不仅满足了业务需求,还确保了良好的用户体验,避免了弹窗滥用带来的用户反感。

posted @ 2025-12-06 17:36  雨花阁  阅读(0)  评论(0)    收藏  举报