Skip to content

Commit e68ed3d

Browse files
authored
Plumbs scrollBehavior into SelectableText so that the scrollbar may be hidden (#158887)
## Description This adds a `scrollBehavior` attribute to `SelectableText` so that the scrolling can be controlled more directly. I added this specifically because it's not possible to turn off the scrollbar on a selectable text, even if you set the scroll physics to be `NeverScrollableScrollPhysics`. We had a UI where we needed to have a clipped, multi-line selectable text field, but have it not be scrollable unless it was expanded in size, and it wasn't possible to hide the scrollbar, but still wanted it to be selectable. ## Tests - Added a test that makes sure that the scroll behavior makes it down to the `Scrollable` in the `EditableText`.
1 parent 3a17b67 commit e68ed3d

File tree

8 files changed

+51
-27
lines changed

8 files changed

+51
-27
lines changed

packages/flutter/lib/src/material/selectable_text.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ class SelectableText extends StatefulWidget {
190190
this.selectionControls,
191191
this.onTap,
192192
this.scrollPhysics,
193+
this.scrollBehavior,
193194
this.semanticsLabel,
194195
this.textHeightBehavior,
195196
this.textWidthBasis,
@@ -247,6 +248,7 @@ class SelectableText extends StatefulWidget {
247248
this.selectionControls,
248249
this.onTap,
249250
this.scrollPhysics,
251+
this.scrollBehavior,
250252
this.semanticsLabel,
251253
this.textHeightBehavior,
252254
this.textWidthBasis,
@@ -412,6 +414,9 @@ class SelectableText extends StatefulWidget {
412414
/// {@macro flutter.widgets.editableText.scrollPhysics}
413415
final ScrollPhysics? scrollPhysics;
414416

417+
/// {@macro flutter.widgets.editableText.scrollBehavior}
418+
final ScrollBehavior? scrollBehavior;
419+
415420
/// {@macro flutter.widgets.Text.semanticsLabel}
416421
final String? semanticsLabel;
417422

@@ -467,6 +472,7 @@ class SelectableText extends StatefulWidget {
467472
properties.add(FlagProperty('selectionEnabled', value: selectionEnabled, defaultValue: true, ifFalse: 'selection disabled'));
468473
properties.add(DiagnosticsProperty<TextSelectionControls>('selectionControls', selectionControls, defaultValue: null));
469474
properties.add(DiagnosticsProperty<ScrollPhysics>('scrollPhysics', scrollPhysics, defaultValue: null));
475+
properties.add(DiagnosticsProperty<ScrollBehavior>('scrollBehavior', scrollBehavior, defaultValue: null));
470476
properties.add(DiagnosticsProperty<TextHeightBehavior>('textHeightBehavior', textHeightBehavior, defaultValue: null));
471477
}
472478
}
@@ -738,6 +744,7 @@ class _SelectableTextState extends State<SelectableText> implements TextSelectio
738744
magnifierConfiguration: widget.magnifierConfiguration ?? TextMagnifier.adaptiveMagnifierConfiguration,
739745
dragStartBehavior: widget.dragStartBehavior,
740746
scrollPhysics: widget.scrollPhysics,
747+
scrollBehavior: widget.scrollBehavior,
741748
autofillHints: null,
742749
contextMenuBuilder: widget.contextMenuBuilder,
743750
),

packages/flutter/lib/src/widgets/editable_text.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,17 +1847,17 @@ class EditableText extends StatefulWidget {
18471847
/// Flutter.
18481848
final String? restorationId;
18491849

1850-
/// {@template flutter.widgets.shadow.scrollBehavior}
1850+
/// {@template flutter.widgets.editableText.scrollBehavior}
18511851
/// A [ScrollBehavior] that will be applied to this widget individually.
18521852
///
18531853
/// Defaults to null, wherein the inherited [ScrollBehavior] is copied and
18541854
/// modified to alter the viewport decoration, like [Scrollbar]s.
1855-
/// {@endtemplate}
18561855
///
18571856
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
18581857
/// [ScrollPhysics] is provided in [scrollPhysics], it will take precedence,
18591858
/// followed by [scrollBehavior], and then the inherited ancestor
18601859
/// [ScrollBehavior].
1860+
/// {@endtemplate}
18611861
///
18621862
/// The [ScrollBehavior] of the inherited [ScrollConfiguration] will be
18631863
/// modified by default to only apply a [Scrollbar] if [maxLines] is greater

packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -710,12 +710,7 @@ class ListWheelScrollView extends StatefulWidget {
710710
/// {@macro flutter.widgets.scrollable.restorationId}
711711
final String? restorationId;
712712

713-
/// {@macro flutter.widgets.shadow.scrollBehavior}
714-
///
715-
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
716-
/// [ScrollPhysics] is provided in [physics], it will take precedence,
717-
/// followed by [scrollBehavior], and then the inherited ancestor
718-
/// [ScrollBehavior].
713+
/// {@macro flutter.widgets.scrollable.scrollBehavior}
719714
///
720715
/// The [ScrollBehavior] of the inherited [ScrollConfiguration] will be
721716
/// modified by default to not apply a [Scrollbar].

packages/flutter/lib/src/widgets/nested_scroll_view.dart

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -313,12 +313,7 @@ class NestedScrollView extends StatefulWidget {
313313
/// {@macro flutter.widgets.scrollable.restorationId}
314314
final String? restorationId;
315315

316-
/// {@macro flutter.widgets.shadow.scrollBehavior}
317-
///
318-
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
319-
/// [ScrollPhysics] is provided in [physics], it will take precedence,
320-
/// followed by [scrollBehavior], and then the inherited ancestor
321-
/// [ScrollBehavior].
316+
/// {@macro flutter.widgets.scrollable.scrollBehavior}
322317
///
323318
/// The [ScrollBehavior] of the inherited [ScrollConfiguration] will be
324319
/// modified by default to not apply a [Scrollbar]. This is because the

packages/flutter/lib/src/widgets/page_view.dart

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -839,12 +839,7 @@ class PageView extends StatefulWidget {
839839
/// Defaults to [HitTestBehavior.opaque].
840840
final HitTestBehavior hitTestBehavior;
841841

842-
/// {@macro flutter.widgets.shadow.scrollBehavior}
843-
///
844-
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
845-
/// [ScrollPhysics] is provided in [physics], it will take precedence,
846-
/// followed by [scrollBehavior], and then the inherited ancestor
847-
/// [ScrollBehavior].
842+
/// {@macro flutter.widgets.scrollable.scrollBehavior}
848843
///
849844
/// The [ScrollBehavior] of the inherited [ScrollConfiguration] will be
850845
/// modified by default to not apply a [Scrollbar].

packages/flutter/lib/src/widgets/scroll_view.dart

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,12 +256,7 @@ abstract class ScrollView extends StatelessWidget {
256256
/// [physics].
257257
final ScrollPhysics? physics;
258258

259-
/// {@macro flutter.widgets.shadow.scrollBehavior}
260-
///
261-
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
262-
/// [ScrollPhysics] is provided in [physics], it will take precedence,
263-
/// followed by [scrollBehavior], and then the inherited ancestor
264-
/// [ScrollBehavior].
259+
/// {@macro flutter.widgets.scrollable.scrollBehavior}
265260
final ScrollBehavior? scrollBehavior;
266261

267262
/// {@template flutter.widgets.scroll_view.shrinkWrap}

packages/flutter/lib/src/widgets/scrollable.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,12 +304,17 @@ class Scrollable extends StatefulWidget {
304304
/// {@endtemplate}
305305
final String? restorationId;
306306

307-
/// {@macro flutter.widgets.shadow.scrollBehavior}
307+
/// {@template flutter.widgets.scrollable.scrollBehavior}
308+
/// A [ScrollBehavior] that will be applied to this widget individually.
309+
///
310+
/// Defaults to null, wherein the inherited [ScrollBehavior] is copied and
311+
/// modified to alter the viewport decoration, like [Scrollbar]s.
308312
///
309313
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
310314
/// [ScrollPhysics] is provided in [physics], it will take precedence,
311315
/// followed by [scrollBehavior], and then the inherited ancestor
312316
/// [ScrollBehavior].
317+
/// {@endtemplate}
313318
final ScrollBehavior? scrollBehavior;
314319

315320
/// {@macro flutter.material.Material.clipBehavior}

packages/flutter/test/widgets/selectable_text_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,36 @@ void main() {
13911391
expect(inputBox.hitTest(BoxHitTestResult(), position: inputBox.globalToLocal(newFourthPos)), isFalse);
13921392
});
13931393

1394+
testWidgets('ScrollBehavior can be overridden', (WidgetTester tester) async {
1395+
await tester.pumpWidget(
1396+
boilerplate(
1397+
child: const SelectableText(
1398+
kMoreThanFourLines,
1399+
dragStartBehavior: DragStartBehavior.down,
1400+
style: TextStyle(color: Colors.black, fontSize: 34.0),
1401+
maxLines: 2,
1402+
),
1403+
),
1404+
);
1405+
expect(tester.widget<EditableText>(find.byType(EditableText)).scrollBehavior, isNull);
1406+
expect(tester.widget<Scrollable>(find.byType(Scrollable)).scrollBehavior, isNotNull);
1407+
1408+
final ScrollBehavior behavior = const ScrollBehavior()..copyWith(scrollbars: false);
1409+
await tester.pumpWidget(
1410+
boilerplate(
1411+
child: SelectableText(
1412+
kMoreThanFourLines,
1413+
dragStartBehavior: DragStartBehavior.down,
1414+
style: const TextStyle(color: Colors.black, fontSize: 34.0),
1415+
maxLines: 2,
1416+
scrollBehavior: behavior,
1417+
),
1418+
),
1419+
);
1420+
expect(tester.widget<EditableText>(find.byType(EditableText)).scrollBehavior, equals(behavior));
1421+
expect(tester.widget<Scrollable>(find.byType(Scrollable)).scrollBehavior, equals(behavior));
1422+
});
1423+
13941424
testWidgets('minLines cannot be greater than maxLines', (WidgetTester tester) async {
13951425
expect(
13961426
() async {
@@ -4578,6 +4608,7 @@ void main() {
45784608
cursorRadius: Radius.zero,
45794609
cursorColor: Color(0xff00ff00),
45804610
scrollPhysics: ClampingScrollPhysics(),
4611+
scrollBehavior: ScrollBehavior(),
45814612
semanticsLabel: 'something else',
45824613
enableInteractiveSelection: false,
45834614
).debugFillProperties(builder);
@@ -4603,6 +4634,7 @@ void main() {
46034634
'cursorColor: ${const Color(0xff00ff00)}',
46044635
'selection disabled',
46054636
'scrollPhysics: ClampingScrollPhysics',
4637+
'scrollBehavior: ScrollBehavior',
46064638
]);
46074639
});
46084640

0 commit comments

Comments
 (0)