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`.
This commit is contained in:
parent
3a17b67353
commit
e68ed3d1f1
@ -190,6 +190,7 @@ class SelectableText extends StatefulWidget {
|
||||
this.selectionControls,
|
||||
this.onTap,
|
||||
this.scrollPhysics,
|
||||
this.scrollBehavior,
|
||||
this.semanticsLabel,
|
||||
this.textHeightBehavior,
|
||||
this.textWidthBasis,
|
||||
@ -247,6 +248,7 @@ class SelectableText extends StatefulWidget {
|
||||
this.selectionControls,
|
||||
this.onTap,
|
||||
this.scrollPhysics,
|
||||
this.scrollBehavior,
|
||||
this.semanticsLabel,
|
||||
this.textHeightBehavior,
|
||||
this.textWidthBasis,
|
||||
@ -412,6 +414,9 @@ class SelectableText extends StatefulWidget {
|
||||
/// {@macro flutter.widgets.editableText.scrollPhysics}
|
||||
final ScrollPhysics? scrollPhysics;
|
||||
|
||||
/// {@macro flutter.widgets.editableText.scrollBehavior}
|
||||
final ScrollBehavior? scrollBehavior;
|
||||
|
||||
/// {@macro flutter.widgets.Text.semanticsLabel}
|
||||
final String? semanticsLabel;
|
||||
|
||||
@ -467,6 +472,7 @@ class SelectableText extends StatefulWidget {
|
||||
properties.add(FlagProperty('selectionEnabled', value: selectionEnabled, defaultValue: true, ifFalse: 'selection disabled'));
|
||||
properties.add(DiagnosticsProperty<TextSelectionControls>('selectionControls', selectionControls, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<ScrollPhysics>('scrollPhysics', scrollPhysics, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<ScrollBehavior>('scrollBehavior', scrollBehavior, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextHeightBehavior>('textHeightBehavior', textHeightBehavior, defaultValue: null));
|
||||
}
|
||||
}
|
||||
@ -738,6 +744,7 @@ class _SelectableTextState extends State<SelectableText> implements TextSelectio
|
||||
magnifierConfiguration: widget.magnifierConfiguration ?? TextMagnifier.adaptiveMagnifierConfiguration,
|
||||
dragStartBehavior: widget.dragStartBehavior,
|
||||
scrollPhysics: widget.scrollPhysics,
|
||||
scrollBehavior: widget.scrollBehavior,
|
||||
autofillHints: null,
|
||||
contextMenuBuilder: widget.contextMenuBuilder,
|
||||
),
|
||||
|
@ -1847,17 +1847,17 @@ class EditableText extends StatefulWidget {
|
||||
/// Flutter.
|
||||
final String? restorationId;
|
||||
|
||||
/// {@template flutter.widgets.shadow.scrollBehavior}
|
||||
/// {@template flutter.widgets.editableText.scrollBehavior}
|
||||
/// A [ScrollBehavior] that will be applied to this widget individually.
|
||||
///
|
||||
/// Defaults to null, wherein the inherited [ScrollBehavior] is copied and
|
||||
/// modified to alter the viewport decoration, like [Scrollbar]s.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
|
||||
/// [ScrollPhysics] is provided in [scrollPhysics], it will take precedence,
|
||||
/// followed by [scrollBehavior], and then the inherited ancestor
|
||||
/// [ScrollBehavior].
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// The [ScrollBehavior] of the inherited [ScrollConfiguration] will be
|
||||
/// modified by default to only apply a [Scrollbar] if [maxLines] is greater
|
||||
|
@ -710,12 +710,7 @@ class ListWheelScrollView extends StatefulWidget {
|
||||
/// {@macro flutter.widgets.scrollable.restorationId}
|
||||
final String? restorationId;
|
||||
|
||||
/// {@macro flutter.widgets.shadow.scrollBehavior}
|
||||
///
|
||||
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
|
||||
/// [ScrollPhysics] is provided in [physics], it will take precedence,
|
||||
/// followed by [scrollBehavior], and then the inherited ancestor
|
||||
/// [ScrollBehavior].
|
||||
/// {@macro flutter.widgets.scrollable.scrollBehavior}
|
||||
///
|
||||
/// The [ScrollBehavior] of the inherited [ScrollConfiguration] will be
|
||||
/// modified by default to not apply a [Scrollbar].
|
||||
|
@ -313,12 +313,7 @@ class NestedScrollView extends StatefulWidget {
|
||||
/// {@macro flutter.widgets.scrollable.restorationId}
|
||||
final String? restorationId;
|
||||
|
||||
/// {@macro flutter.widgets.shadow.scrollBehavior}
|
||||
///
|
||||
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
|
||||
/// [ScrollPhysics] is provided in [physics], it will take precedence,
|
||||
/// followed by [scrollBehavior], and then the inherited ancestor
|
||||
/// [ScrollBehavior].
|
||||
/// {@macro flutter.widgets.scrollable.scrollBehavior}
|
||||
///
|
||||
/// The [ScrollBehavior] of the inherited [ScrollConfiguration] will be
|
||||
/// modified by default to not apply a [Scrollbar]. This is because the
|
||||
|
@ -839,12 +839,7 @@ class PageView extends StatefulWidget {
|
||||
/// Defaults to [HitTestBehavior.opaque].
|
||||
final HitTestBehavior hitTestBehavior;
|
||||
|
||||
/// {@macro flutter.widgets.shadow.scrollBehavior}
|
||||
///
|
||||
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
|
||||
/// [ScrollPhysics] is provided in [physics], it will take precedence,
|
||||
/// followed by [scrollBehavior], and then the inherited ancestor
|
||||
/// [ScrollBehavior].
|
||||
/// {@macro flutter.widgets.scrollable.scrollBehavior}
|
||||
///
|
||||
/// The [ScrollBehavior] of the inherited [ScrollConfiguration] will be
|
||||
/// modified by default to not apply a [Scrollbar].
|
||||
|
@ -256,12 +256,7 @@ abstract class ScrollView extends StatelessWidget {
|
||||
/// [physics].
|
||||
final ScrollPhysics? physics;
|
||||
|
||||
/// {@macro flutter.widgets.shadow.scrollBehavior}
|
||||
///
|
||||
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
|
||||
/// [ScrollPhysics] is provided in [physics], it will take precedence,
|
||||
/// followed by [scrollBehavior], and then the inherited ancestor
|
||||
/// [ScrollBehavior].
|
||||
/// {@macro flutter.widgets.scrollable.scrollBehavior}
|
||||
final ScrollBehavior? scrollBehavior;
|
||||
|
||||
/// {@template flutter.widgets.scroll_view.shrinkWrap}
|
||||
|
@ -304,12 +304,17 @@ class Scrollable extends StatefulWidget {
|
||||
/// {@endtemplate}
|
||||
final String? restorationId;
|
||||
|
||||
/// {@macro flutter.widgets.shadow.scrollBehavior}
|
||||
/// {@template flutter.widgets.scrollable.scrollBehavior}
|
||||
/// A [ScrollBehavior] that will be applied to this widget individually.
|
||||
///
|
||||
/// Defaults to null, wherein the inherited [ScrollBehavior] is copied and
|
||||
/// modified to alter the viewport decoration, like [Scrollbar]s.
|
||||
///
|
||||
/// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
|
||||
/// [ScrollPhysics] is provided in [physics], it will take precedence,
|
||||
/// followed by [scrollBehavior], and then the inherited ancestor
|
||||
/// [ScrollBehavior].
|
||||
/// {@endtemplate}
|
||||
final ScrollBehavior? scrollBehavior;
|
||||
|
||||
/// {@macro flutter.material.Material.clipBehavior}
|
||||
|
@ -1391,6 +1391,36 @@ void main() {
|
||||
expect(inputBox.hitTest(BoxHitTestResult(), position: inputBox.globalToLocal(newFourthPos)), isFalse);
|
||||
});
|
||||
|
||||
testWidgets('ScrollBehavior can be overridden', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
boilerplate(
|
||||
child: const SelectableText(
|
||||
kMoreThanFourLines,
|
||||
dragStartBehavior: DragStartBehavior.down,
|
||||
style: TextStyle(color: Colors.black, fontSize: 34.0),
|
||||
maxLines: 2,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(tester.widget<EditableText>(find.byType(EditableText)).scrollBehavior, isNull);
|
||||
expect(tester.widget<Scrollable>(find.byType(Scrollable)).scrollBehavior, isNotNull);
|
||||
|
||||
final ScrollBehavior behavior = const ScrollBehavior()..copyWith(scrollbars: false);
|
||||
await tester.pumpWidget(
|
||||
boilerplate(
|
||||
child: SelectableText(
|
||||
kMoreThanFourLines,
|
||||
dragStartBehavior: DragStartBehavior.down,
|
||||
style: const TextStyle(color: Colors.black, fontSize: 34.0),
|
||||
maxLines: 2,
|
||||
scrollBehavior: behavior,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(tester.widget<EditableText>(find.byType(EditableText)).scrollBehavior, equals(behavior));
|
||||
expect(tester.widget<Scrollable>(find.byType(Scrollable)).scrollBehavior, equals(behavior));
|
||||
});
|
||||
|
||||
testWidgets('minLines cannot be greater than maxLines', (WidgetTester tester) async {
|
||||
expect(
|
||||
() async {
|
||||
@ -4578,6 +4608,7 @@ void main() {
|
||||
cursorRadius: Radius.zero,
|
||||
cursorColor: Color(0xff00ff00),
|
||||
scrollPhysics: ClampingScrollPhysics(),
|
||||
scrollBehavior: ScrollBehavior(),
|
||||
semanticsLabel: 'something else',
|
||||
enableInteractiveSelection: false,
|
||||
).debugFillProperties(builder);
|
||||
@ -4603,6 +4634,7 @@ void main() {
|
||||
'cursorColor: ${const Color(0xff00ff00)}',
|
||||
'selection disabled',
|
||||
'scrollPhysics: ClampingScrollPhysics',
|
||||
'scrollBehavior: ScrollBehavior',
|
||||
]);
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user