今日已更新 240 条资讯 | 累计 23823 条内容
关于我们

onPreviewKeyEvent vs onKeyEvent on Android TV: A Subtle D-Pad Bug

Akshay Nikhare 2026年07月24日 14:22 1 次阅读 来源:Dev.to

The bug report was simple: long-pressing the d-pad center button on a channel card should toggle the favorite — it wasn't working reliably. On some devices it fired once and stopped. On others it didn't fire at all on long-press. The fix was changing onKeyEvent to onPreviewKeyEvent in one Composable. The reason why is worth understanding. Background: Two Event Handlers in Compose Jetpack Compose exposes two modifier-level hooks for key input: Modifier . onKeyEvent { keyEvent -> .. . } Modifier . onPreviewKeyEvent { keyEvent -> .. . } They sound equivalent. They're not. The difference is where they sit in the event propagation chain . How Android TV Routes D-Pad Events When a user presses a key on a TV remote, Android routes the event through a dispatch tree: Activity └─ ViewGroup (root) └─ FocusedComposable └─ Child Composables The event travels down first (capture phase), then up (bubble phase): Capture (top → focused node): onPreviewKeyEvent handlers fire here, outermost first. Bubble (focused node → top): onKeyEvent handlers fire here, innermost first. onPreviewKeyEvent is the capture phase. onKeyEvent is the bubble phase. Why This Matters for Long-Press Android TV handles long-press recognition at the framework level. When you hold the d-pad center button: A KeyEvent.ACTION_DOWN fires immediately. If the key is held, the framework generates repeated ACTION_DOWN events at the key repeat rate. ACTION_UP fires when the button is released. The long-press callback that Compose's focus system uses for "confirm" actions (select, activate) consumes ACTION_DOWN during the bubble phase — specifically to prevent the holding action from also triggering the tap action. When the ChannelCard had a click handler wired for the primary action and onKeyEvent for the long-press toggle, the click handler's bubble-phase consumption of ACTION_DOWN was racing with the long-press handler. On some devices the click handler won, swallowing the event before the long-press code ran. The Fix

本文内容来源于互联网,版权归原作者所有
查看原文