SingleChildTwoDimensionalScrollView class

A box in which a single widget can be scrolled in two dimensions.

This widget is useful when you have a single box that will normally be entirely visible, for example a clock face in a time picker, but you need to make sure it can be scrolled if the container gets too small in two axes

Sometimes a layout is designed around the flexible properties of a Column + Row, but there is the concern that in some cases, there might not be enough room to see the entire contents. This could be because some devices have unusually small screens, a resized small (sometimes due to virtual keyboard), or because the application can be used in landscape mode where the aspect ratio isn't what was originally envisioned, or because the application is being shown in a small window in split-screen mode. In any case, as a result, it might make sense to wrap the layout in a SingleChildTwoDimensionalScrollView.

Doing so, however, usually results in a conflict between the Column/Row, which typically tries to grow as big as it can, and the SingleChildTwoDimensionalScrollView, which provides its children with an infinite amount of space.

To resolve this apparent conflict, there are a couple of techniques, as discussed below.

Centering, spacing, or aligning fixed-height content

If the content has fixed (or intrinsic) dimensions but needs to be spaced out, centered, or otherwise positioned using the Flex layout model of a Column, / Row the following technique can be used to provide the Column / Row with a minimum dimension while allowing it to shrink-wrap the contents when there isn't enough room to apply these spacing or alignment needs.

A LayoutBuilder is used to obtain the size of the viewport (implicit ly via the constraints that the SingleChildTwoDimensionalScrollView sees, since viewports typically grow to fit their maximum width/height constraint). Then, inside the scroll view, a ConstrainedBox is used to set the minimum height / width of the Column and or Row.

The Column has no Expanded children, so rather than take on the infinite height from its BoxConstraints.maxHeight, (the viewport provides no maximum height constraint), it automatically tries to shrink to fit its children. It cannot be smaller than its BoxConstraints.minHeight, though, and It therefore becomes the bigger of the minimum height provided by the ConstrainedBox and the sum of the heights of the children.

If the children aren't enough to fit that minimum size, the Column / Row ends up with some remaining space to allocate as specified by its Column.mainAxisAlignment / Row.mainAxisAlignment argument.

{@tool dartpad} In this example, the child is able to scroll in two dimensions.

When using this technique, Expanded and Flexible are not useful, because in both cases the "available space" is infinite (since this is in a viewport).

** See code in examples/lib/main.dart ** {@end-tool}

Inheritance

Constructors

SingleChildTwoDimensionalScrollView({Key? key, EdgeInsetsGeometry? padding, bool reverseVertical = false, bool reverseHorizontal = false, bool? primary, ScrollPhysics? verticalPhysics, ScrollController? verticalController, ScrollPhysics? horizontalPhysics, ScrollController? horizontalController, Widget? child, DragStartBehavior dragStartBehavior = DragStartBehavior.start, Clip clipBehavior = Clip.hardEdge, HitTestBehavior hitTestBehavior = HitTestBehavior.opaque, ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, DiagonalDragBehavior diagonalDragBehavior = DiagonalDragBehavior.none, String? restorationId, double? cacheExtent, CacheExtentStyle? cacheExtentStyle})
Creates a box in which a single widget can be scrolled in two dimensions.
const

Properties

cacheExtent double?
Deprecated. Use scrollCacheExtent instead.
final
cacheExtentStyle CacheExtentStyle?
Deprecated. Use scrollCacheExtent instead.
final
child Widget?
The widget that scrolls in two dimensions.
final
clipBehavior Clip
The content will be clipped (or not) according to this option.
final
diagonalDragBehavior DiagonalDragBehavior
Whether scrolling gestures should lock to one axis, allow free movement in both axes, or be evaluated on a weighted scale.
final
dragStartBehavior DragStartBehavior
Determines the way that drag start behavior is handled.
final
hashCode int
The hash code for this object.
no setterinherited
hitTestBehavior HitTestBehavior
Defines the behavior of gesture detector used in this Scrollable.
final
horizontalController ScrollController?
An object that can be used to control the position to which this horizontal scroll axis is scrolled.
final
horizontalPhysics ScrollPhysics?
How the horizontal scroll view should respond to user input.
final
key Key?
Controls how one widget replaces another widget in the tree.
finalinherited
keyboardDismissBehavior ScrollViewKeyboardDismissBehavior
The ScrollViewKeyboardDismissBehavior defines how this ScrollView will dismiss the keyboard automatically.
final
padding EdgeInsetsGeometry?
The amount of space by which to inset the child.
final
primary bool?
Whether this is the primary scroll view associated with the parent PrimaryScrollController.
final
restorationId String?
Restoration ID to save and restore the scroll offset of the scrollable.
final
reverseHorizontal bool
Whether the scroll view scrolls in the reading direction.
final
reverseVertical bool
Whether the vertical scroll view scrolls in the reading direction.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
verticalController ScrollController?
An object that can be used to control the position to which this vertical scroll axis is scrolled.
final
verticalPhysics ScrollPhysics?
How the vertical scroll axis should respond to user input.
final

Methods

build(BuildContext context) Widget
Describes the part of the user interface represented by this widget.
override
createElement() StatelessElement
Creates a StatelessElement to manage this widget's location in the tree.
inherited
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
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
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

Operators

operator ==(Object other) bool
The equality operator.
inherited