Render Picker as a spinner#15
Merged
Merged
Conversation
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.
Completes the pickable controls:
Pickerrenders as a nativeSpinner, bound to its genericSelectionValue. Uses theSpinnerconstructors added upstream in PureSwift/Android#47.Option extraction
The interesting part is recovering the options.
Picker.bodydoesn't hand the renderer its rows directly — it wraps them in a generatedForEachof_PickerElements, each inside conditional content, andForEachadditionally wraps every row in an identified view. The renderer flattens that tree recursively (descending group views and identified views) down to the_PickerElementrows, then walks each row's modifiers for thetag(_:)that associates it with its selection value — the same trait-walking approachTabViewuses for its tags.Row titles come from the
Textinside each row, unwrapping any modifiers around it (including the tag itself). Rows that aren't text render as an empty entry, since a spinner shows plain strings rather than arbitrary views.The
ForEach-with-data case (ForEach(items, id: \.self)), where the row identity is the selection value, is handled through the container'selementspath.Selection
Selection maps to and from adapter indices: the listener looks up the tapped position in the extracted values and writes it to the binding, guarded against no-op writes; updates set the spinner's position from the bound value. The listener is attached after the adapter so the initial selection doesn't fire a callback.
The listener bridge (
SpinnerOnItemSelectedListener) follows the convention from the slider/text-field bridges: the Kotlin side collapses the interface callbacks into oneexternalmethod forwarding only the position, keeping the JNI signature aligned with the Swift declaration.The spinner spans the stack like the other horizontal controls — at its intrinsic width it collapses to just the dropdown arrow, hiding the selected value.
Verification
On the emulator: the spinner shows the selected value, the dropdown opens with all three options, and selecting one updates both the spinner and the bound
@State(Apple → Banana → Cherry across builds).