DetectScroll class
The DetectScroll can detect if the content of a Scrollable is larger than the Scrollable itself, which means that the content can be scrolled, and that a scrollbar is likely visible. It can also tell you the probable width of that scrollbar.
This is useful for positioning widgets relative to the scrollbar, so that the scrollbar doesn't overlap them. This can be important when the scrollbar is permanently visible, usually on the Web and desktop.
Note that DetectScroll will only detect the scrolling of its closest scrollable
descendant (a scrollable is a SingleChildScrollView, ListView, GridView etc).
Usually, you'd wrap the scrollable you care about directly with a DetectScroll.
For example:
DetectScroll(
child: SingleChildScrollView(
child: Column( ...
...
);
To get the current scroll state and the scrollbar width, descendants can call:
bool canScroll = DetectScroll.of(context).canScroll;
double width = DetectScroll.of(context).scrollbarWidth;
For example, suppose you want to add a help button to the top-right corner of a scrollable, and account for the scrollbar width only if it's visible:
bool canScroll = DetectScroll.of(context).canScroll;
double width = DetectScroll.of(context).scrollbarWidth;
return Stack(
children: [
child,
Positioned(
right: canScroll ? width : 0,
top: 0,
child: HelpButton(),
),
],
);
Another alternative is using the optional onChange callback:
DetectScroll(
onChange: ({
required bool canScroll,
required double width,
}) {
// Do something.
}
child: ...
),
In more detail:
The DetectScroll actually only detects if its subtree can scroll, in other words, that its closest descendant Scrollable has enough content so that not all of it fits the available visible space, and then informs its descendants about this fact.
Note this doesn't mean there is actually a scrollbar visible, but only that the content can be scrolled. For this reason, you should use it to detect scrollbars only when a scrollbar is always shown when the content doesn't fit (like on the web or desktop), or when you're using a custom scrollbar that is always visible.
Regarding the width of the scrollbar provided by DetectScroll, this information is calculated from the current theme at the DetectScroll. For this reason, if you use this width, make sure the scrollbar is actually using this same theme.
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatefulWidget
- DetectScroll
- Available extensions
Constructors
- DetectScroll({Key? key, required Widget child, void onChange({required bool canScroll, required double scrollbarWidth})?, bool cancelNotificationBubbling = false})
-
The DetectScroll can detect if the content of a Scrollable is larger than the
Scrollable itself, which means that the content can be scrolled, and that a scrollbar
is likely visible. It can also tell you the probable width of that scrollbar.
const
Properties
- cancelNotificationBubbling → bool
-
If true, the DetectScroll will cancel the ScrollMetricsNotification bubbling.
If false, the notification will be allowed to continue to be dispatched to further
ancestors. The default is false.
final
- child → Widget
-
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- makeRefreshable → Widget
-
Available on Widget?, provided by the WidgetExtension extension
Make your any widget refreshable with RefreshIndicator on topno setter - onChange → void Function({required bool canScroll, required double scrollbarWidth})?
-
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
addMaterialWidget(
) → Material -
Available on Widget, provided by the GenericExtensions extension
-
addTooltipWidget(
String toolTip) → Tooltip -
Available on Widget, provided by the GenericExtensions extension
-
animate(
{Key? key, List< Effect> ? effects, AnimateCallback? onInit, AnimateCallback? onPlay, AnimateCallback? onComplete, bool? autoPlay, Duration? delay, AnimationController? controller, Adapter? adapter, double? target, double? value}) → Animate -
Available on Widget, provided by the AnimateWidgetExtensions extension
Wraps the target Widget in an Animate instance, and returns the instance for chaining calls. Ex.myWidget.animate()is equivalent toAnimate(child: myWidget). -
borderRadius(
[BorderRadiusGeometry? borderRadius]) → Widget -
Available on Widget, provided by the GenericExtensions extension
-
boxDecoration(
[BoxDecoration? boxDecoration]) → Widget -
Available on Widget, provided by the GenericExtensions extension
-
center(
{double? heightFactor, double? widthFactor}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
set parent widget in center -
colorFilter(
[ColorFilter? colorFilter]) → Widget -
Available on Widget, provided by the GenericExtensions extension
set parent widget in center -
cornerRadiusWithClipRRect(
double radius) → ClipRRect -
Available on Widget?, provided by the WidgetExtension extension
add corner radius -
cornerRadiusWithClipRRectOnly(
{int bottomLeft = 0, int bottomRight = 0, int topLeft = 0, int topRight = 0}) → ClipRRect -
Available on Widget?, provided by the WidgetExtension extension
add custom corner radius each side -
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree.
inherited
-
createState(
) → State< DetectScroll> -
Creates the mutable state for this widget at a given location in the tree.
override
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
inherited
-
expand(
{int flex = 1}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add Expanded to parent widget -
fit(
{BoxFit? fit, AlignmentGeometry? alignment}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add FittedBox to parent widget -
flexible(
{int flex = 1, FlexFit? fit}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add Flexible to parent widget -
launch<
T> (BuildContext context, {bool isNewTask = false, PageRouteAnimation? pageRouteAnimation, Duration? duration, String? routeName, Object? routeArguments}) → Future< T?> -
Available on Widget?, provided by the WidgetExtension extension
Launch a new screen -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
onTap(
Function? function, {BorderRadius? borderRadius, Color? splashColor, Color? hoverColor, Color? highlightColor, Color? focusColor, WidgetStateProperty< Color?> ? overlayColor}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add tap to parent widget -
opacity(
{required double opacity, int durationInSecond = 1, Duration? duration}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add opacity to parent widget -
paddingAll(
double padding) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding all -
paddingBottom(
double bottom) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding bottom -
paddingDirectional(
{double start = 0.0, double top = 0.0, double end = 0.0, double bottom = 0.0}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
-
paddingLeft(
double left) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding left -
paddingOnly(
{double top = 0.0, double left = 0.0, double bottom = 0.0, double right = 0.0}) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return custom padding from each side -
paddingRight(
double right) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding right -
paddingSymmetric(
{double vertical = 0.0, double horizontal = 0.0}) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding symmetric -
paddingTop(
double top) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding top -
rotate(
{required double angle, bool transformHitTests = true, Offset? origin}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add rotation to parent widget -
scale(
{required double scale, Offset? origin, AlignmentGeometry? alignment, bool transformHitTests = true}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add scaling to parent widget -
toDiagnosticsNode(
{String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by DiagnosticsNode.toStringDeep.
inherited
-
tooltip(
{required String msg}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
-
toString(
{DiagnosticLevel minLevel = DiagnosticLevel.info}) → String -
A string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String -
Returns a string representation of this node and its descendants.
inherited
-
toStringShallow(
{String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a one-line detailed description of the object.
inherited
-
toStringShort(
) → String -
A short, textual description of this widget.
inherited
-
translate(
{required Offset offset, bool transformHitTests = true, Key? key}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add translate to parent widget -
validate(
{Widget value = const SizedBox()}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
Validate given widget is not null and returns given value if null. -
visible(
bool visible, {Widget? defaultWidget}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
set visibility -
withHeight(
double height) → SizedBox -
Available on Widget?, provided by the WidgetExtension extension
With custom height -
withRoundedCorners(
{Color backgroundColor = whiteColor, BorderRadius borderRadius = const BorderRadius.all(Radius.circular(8.0)), LinearGradient? gradient, BoxBorder? border, List< BoxShadow> ? boxShadow, DecorationImage? decorationImage, BoxShape boxShape = BoxShape.rectangle}) → Container -
Available on Widget?, provided by the WidgetExtension extension
-
withScroll(
{ScrollPhysics? physics, EdgeInsetsGeometry? padding, Axis scrollDirection = Axis.vertical, ScrollController? controller, DragStartBehavior dragStartBehavior = DragStartBehavior.start, bool? primary, required bool reverse}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
-
withShaderMask(
List< Color> colors, {BlendMode blendMode = BlendMode.srcATop}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
Wrap with ShaderMask widget -
withShaderMaskGradient(
Gradient gradient, {BlendMode blendMode = BlendMode.srcATop}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
Wrap with ShaderMask widget Gradient -
withShadow(
{Color bgColor = whiteColor, Color shadowColor = Colors.black12, dynamic blurRadius = 10.0, dynamic spreadRadius = 0.0, Offset offset = const Offset(0.0, 0.0), LinearGradient? gradient, BoxBorder? border, DecorationImage? decorationImage, BoxShape boxShape = BoxShape.rectangle}) → Container -
Available on Widget?, provided by the WidgetExtension extension
-
withSize(
{double width = 0.0, double height = 0.0}) → SizedBox -
Available on Widget?, provided by the WidgetExtension extension
With custom height and width -
withTooltip(
{required String msg}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
Validate given widget is not null and returns given value if null. -
withVisibility(
bool visible, {Widget? replacement, bool maintainAnimation = false, bool maintainState = false, bool maintainSize = false, bool maintainSemantics = false, bool maintainInteractivity = false}) → Visibility -
Available on Widget?, provided by the WidgetExtension extension
set widget visibility -
withWidth(
double width) → SizedBox -
Available on Widget?, provided by the WidgetExtension extension
With custom width
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Methods
-
of(
BuildContext context) → _DetectScrollInherited - Allows descendants to get the scroll state. Example: