Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit a5215ce

Browse files
author
Jonah Williams
authored
Add hasImplicitScrolling SemanticFlag and support in Android bridge (#5941)
1 parent 4681351 commit a5215ce

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

lib/ui/semantics.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ class SemanticsFlag {
279279
static const int _kIsLiveRegionIndex = 1 << 15;
280280
static const int _kHasToggledStateIndex = 1 << 16;
281281
static const int _kIsToggledIndex = 1 << 17;
282+
static const int _kHasImplicitScrollingIndex = 1 << 18;
282283

283284
const SemanticsFlag._(this.index);
284285

@@ -465,6 +466,15 @@ class SemanticsFlag {
465466
/// * [SemanticsFlag.hasToggledState], which enables a toggled state.
466467
static const SemanticsFlag isToggled = const SemanticsFlag._(_kIsToggledIndex);
467468

469+
/// Whether the platform can scroll the semantics node when the user attempts
470+
/// to move focus to an offscreen child.
471+
///
472+
/// For example, a [ListView] widget has implicit scrolling so that users can
473+
/// easily move to the next visible set of children. A [TabBar] widget does
474+
/// not have implicit scrolling, so that users can navigate into the tab
475+
/// body when reaching the end of the tab bar.
476+
static const SemanticsFlag hasImplicitScrolling = const SemanticsFlag._(_kHasImplicitScrollingIndex);
477+
468478
/// The possible semantics flags.
469479
///
470480
/// The map's key is the [index] of the flag and the value is the flag itself.
@@ -487,6 +497,7 @@ class SemanticsFlag {
487497
_kIsLiveRegionIndex: isLiveRegion,
488498
_kHasToggledStateIndex: hasToggledState,
489499
_kIsToggledIndex: isToggled,
500+
_kHasImplicitScrollingIndex: hasImplicitScrolling,
490501
};
491502

492503
@override
@@ -528,6 +539,8 @@ class SemanticsFlag {
528539
return 'SemanticsFlag.hasToggledState';
529540
case _kIsToggledIndex:
530541
return 'SemanticsFlag.isToggled';
542+
case _kHasImplicitScrollingIndex:
543+
return 'SemanticsFlag.hasImplicitScrolling';
531544
}
532545
return null;
533546
}

shell/platform/android/io/flutter/view/AccessibilityBridge.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ enum Flag {
9292
IS_IMAGE(1 << 14),
9393
IS_LIVE_REGION(1 << 15),
9494
HAS_TOGGLED_STATE(1 << 16),
95-
IS_TOGGLED(1 << 17);
95+
IS_TOGGLED(1 << 17),
96+
HAS_IMPLICIT_SCROLLING(1 << 18);
9697

9798
Flag(int value) {
9899
this.value = value;
@@ -256,8 +257,15 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
256257
|| object.hasAction(Action.SCROLL_RIGHT) || object.hasAction(Action.SCROLL_DOWN)) {
257258
result.setScrollable(true);
258259
// This tells Android's a11y to send scroll events when reaching the end of
259-
// the visible viewport of a scrollable.
260-
result.setClassName("android.widget.ScrollView");
260+
// the visible viewport of a scrollable, unless the node itself does not
261+
// allow implicit scrolling - then we leave the className as view.View.
262+
if (object.hasFlag(Flag.HAS_IMPLICIT_SCROLLING)) {
263+
if (object.hasAction(Action.SCROLL_LEFT) || object.hasAction(Action.SCROLL_RIGHT)) {
264+
result.setClassName("android.widget.HorizontalScrollView");
265+
} else {
266+
result.setClassName("android.widget.ScrollView");
267+
}
268+
}
261269
// TODO(ianh): Once we're on SDK v23+, call addAction to
262270
// expose AccessibilityAction.ACTION_SCROLL_LEFT, _RIGHT,
263271
// _UP, and _DOWN when appropriate.

0 commit comments

Comments
 (0)