Fix lightweight Picker traversal controls when non-traversable#5091
Merged
shai-almog merged 1 commit intoMay 29, 2026
Merged
Conversation
acae645 to
c10183e
Compare
Contributor
Author
|
@shai-almog I used generative AI to create this pull request, which addresses a real-world problem on my Android device. The fix seems reasonable and straightforward, and I don't think testing it locally by recompiling CN1 is necessary. However, if you would like me to do so, I can. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Pickernext/previous controls when the picker itself is not traversable.Component#setTraversable(false)/ preferred tab index traversal.Problem
Pickerdefaults into the focus traversal order by setting a preferred tab index in its constructor. Applications can opt a picker out of traversal viasetTraversable(false), which makes the component absent from the form's tab iterator.The lightweight picker popup still calls
Form#getTabIterator(Picker.this)to decide whether to show previous/next buttons. When the picker has been made non-traversable, the tab iterator cannot find it and initializes its current position to-1. In that statehasNext()may still return the first traversable component in the form, andhasPrevious()may return the last traversable component. As a result, the lightweight popup can display traversal controls even though the picker opted out of traversal.Pressing one of those controls then calls
getNextComponent(Picker.this)/getPreviousComponent(Picker.this), requests focus on an unrelated component, and starts editing it. On Android this can surface as an unexpected native text editor appearing for a laterTextFieldimmediately after the picker closes.Fix
Gate both sides of the lightweight picker traversal behavior on
Picker.this.isTraversable():COMMAND_NEXT/COMMAND_PREVonly attempt focus transfer for traversable pickers.This preserves the existing traversal behavior for normal traversable pickers while respecting applications that explicitly call
setTraversable(false).Verification
Pickerfollowed by numericTextFields.picker.setTraversable(false)still shows the previous/next arrow buttons; pressing an arrow closes the picker and starts editing a numeric text field.git diff --checkon the branch.