Jetpack Compose `ACTION_HOVER_EXIT` 事件异常解决方案

Jetpack Compose 1.6.6 版本中 ACTION_HOVER_EXIT 事件异常解决方案

问题现象

在 Android 应用开发中使用 Jetpack Compose 1.6.6 版本时,部分设备会出现以下崩溃日志:

java.lang.IllegalStateException: The ACTION_HOVER_EXIT event was not cleared.
    at androidx.compose.ui.platform.AndroidComposeView.sendHoverExitEvent$lambda$5(AndroidComposeView.android.kt:565)
    ...

问题背景

这个错误通常出现在以下场景:

  1. 使用鼠标或触控笔操作界面时
  2. 在平板设备或 Chrome OS 设备上
  3. 快速滑动或频繁触发悬停事件时

原因分析

该问题的根本原因是 Compose 运行时在处理 ACTION_HOVER_EXIT 事件时,事件状态未被正确清除。即使在使用最新的 1.6.6 版本时,由于以下原因仍可能出现:

  1. 设备厂商对 Android 系统的定制修改
  2. 第三方输入设备驱动发送了不规范的事件序列
  3. Compose 与传统 View 系统混合使用时事件流被污染

解决方案

方案一:事件拦截处理(推荐)

AndroidComposeView(this).apply {
    setOnGenericMotionListener { _, event ->
        when (event.action) {
            MotionEvent.ACTION_HOVER_EXIT -> {
                event.action = MotionEvent.ACTION_CANCEL
                true
            }
            else -> false
        }
    }
}

优点

  • 保留悬停功能
  • 针对性强

缺点

  • 需要为每个 ComposeView 设置

方案二:全局配置(适合纯触控应用)

// 在 Application 类中:
@SuppressLint("DiscouragedPrivateApi")
fun disableHoverEventsGlobally() {
    try {
        val field = AndroidComposeView::class.java
            .getDeclaredField("shouldDispatchHoverEvents")
        field.isAccessible = true
        field.setBoolean(null, false)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

优点

  • 一劳永逸
  • 适合不需要悬停效果的应用

缺点

  • 使用反射,可能有兼容性问题
  • 会完全禁用悬停效果

方案三:升级到预览版本

implementation 'androidx.compose.ui:ui:1.7.0-alpha03'

优点

  • 官方修复方案
  • 从根本上解决问题

缺点

  • 使用 alpha 版本可能存在稳定性风险

验证方法

  1. 最小化测试:
class TestActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text("Hover Test") // 仅显示简单文本测试
        }
    }
}
  1. 监控日志:
adb logcat | grep -E "HOVER|Compose"

最佳实践建议

  1. 对于生产环境应用
    • 优先使用方案一(事件拦截)
    • 在关键界面添加异常捕获
  2. 对于新开发项目
    • 考虑使用 Compose 1.7.0-alpha 版本
    • 充分测试各种输入设备
  3. 兼容性处理
fun isHoverBrokenDevice(): Boolean {
    return Build.MANUFACTURER.equals("特定问题厂商", ignoreCase = true) 
            || Build.MODEL.contains("Chromebook")
}

延伸阅读

  1. 官方 Issue 追踪

  2. Compose 输入事件处理文档

  3. Compose 1.7.0 变更日志

  4. Stack Overflow: Compose app crashes when scrolling with a mouse

    Google Issue Tracker: The ACTION_HOVER_EXIT event was not cleared.

总结

Jetpack Compose 1.6.6 中的 Hover 事件问题可以通过多种方式解决。建议根据项目实际情况选择合适的方案,并及时关注官方更新以获取永久性修复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值