Skip to content

Android: navbar segments don't move their selection when tapped, so click: segments stick #116

Open

Description

@joemasilotti

NavbarSegments takes its selection entirely from the page: SegmentedButton(selected = segment.selected, ...), and a tap only calls onSegmentTapped. The KDoc says the page's next render moves the selection "exactly like iOS", but that is not what iOS does. iOS builds the control with UISegmentedControl(frame: .zero, actions:), so UIKit moves selectedSegmentIndex itself the moment a segment is tapped, and the report that follows only re-confirms it.

The difference is invisible for an href: segment, because the navigation produces a new page and a new report and the selection catches up before anyone looks. It is very visible for a click: segment. Nothing navigates, so nothing reports, and the control stays on the old segment while the page content changes underneath it. The user taps "All time", sees all-time numbers, and the control still reads "This year".

click: is documented in the segment options table and is the natural choice for switching between panels that are already on the page, so this takes nothing unusual to reach.

The workaround a page needs today is to move data-native-selected itself and then call RubyNative.checkNow(), because the bridge's MutationObserver is { childList: true, subtree: true } and flipping an attribute in place reports nothing on its own. That works, but it asks the web side to know a platform implementation detail that iOS needs nothing for, and a page that omits it is broken on Android only.

Moving the selection optimistically on tap and letting the next report correct it would match iOS and make click: behave the same on both platforms.

Related, same component

The label is Text(segment.title.orEmpty(), maxLines = 1, overflow = TextOverflow.Ellipsis), and it truncates earlier than the available width suggests. On a Pixel 9 Pro with two segments and most of the bar free, "This year" rendered as "This ye…" while "All time", one character shorter, fit. iOS sets apportionsSegmentWidthsByContent = true and shows both in full.

Worth checking whether the icon = {} slot is still taking layout space. It was passed an empty composable rather than omitted, to suppress the Material checkmark, and the comment there already notes that the icon shifts the labels.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    androidiOS implements this but Android does not.bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions