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)
...
问题背景
这个错误通常出现在以下场景:
- 使用鼠标或触控笔操作界面时
- 在平板设备或 Chrome OS 设备上
- 快速滑动或频繁触发悬停事件时
原因分析
该问题的根本原因是 Compose 运行时在处理 ACTION_HOVER_EXIT
事件时,事件状态未被正确清除。即使在使用最新的 1.6.6 版本时,由于以下原因仍可能出现:
- 设备厂商对 Android 系统的定制修改
- 第三方输入设备驱动发送了不规范的事件序列
- 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 版本可能存在稳定性风险
验证方法
- 最小化测试:
class TestActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text("Hover Test") // 仅显示简单文本测试
}
}
}
- 监控日志:
adb logcat | grep -E "HOVER|Compose"
最佳实践建议
- 对于生产环境应用:
- 优先使用方案一(事件拦截)
- 在关键界面添加异常捕获
- 对于新开发项目:
- 考虑使用 Compose 1.7.0-alpha 版本
- 充分测试各种输入设备
- 兼容性处理:
fun isHoverBrokenDevice(): Boolean {
return Build.MANUFACTURER.equals("特定问题厂商", ignoreCase = true)
|| Build.MODEL.contains("Chromebook")
}
延伸阅读
-
官方 Issue 追踪
-
Compose 输入事件处理文档
-
Compose 1.7.0 变更日志
-
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 事件问题可以通过多种方式解决。建议根据项目实际情况选择合适的方案,并及时关注官方更新以获取永久性修复。