Unverified Commit c482cc4b authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Add some suggestions for using Column with a SingleChildScrollView (#16500)

parent ca35ddd4
......@@ -9,6 +9,7 @@
// Code is denoted by markdown ```dart / ``` markers.
//
// Only code in "## Sample code" or "### Sample code" sections is examined.
// Subheadings can also be specified, as in "## Sample code: foo".
//
// There are several kinds of sample code you can specify:
//
......@@ -162,7 +163,10 @@ Future<Null> main() async {
assert(block.isEmpty);
startLine = new Line(file.path, lineNumber + 1, 3);
inPreamble = true;
} else if (trimmedLine == '/// ## Sample code' || trimmedLine == '/// ### Sample code') {
} else if (trimmedLine == '/// ## Sample code' ||
trimmedLine.startsWith('/// ## Sample code:') ||
trimmedLine == '/// ### Sample code' ||
trimmedLine.startsWith('/// ### Sample code:')) {
inSampleSection = true;
foundDart = false;
sampleCodeSections += 1;
......
......@@ -3744,6 +3744,8 @@ class Row extends Flex {
/// * [Expanded], to indicate children that should take all the remaining room.
/// * [Flexible], to indicate children that should share the remaining room but
/// that may size smaller (leaving some remaining room unused).
/// * [SingleChildScrollView], whose documentation discusses some ways to
/// use a [Column] inside a scrolling container.
/// * The [catalog of layout widgets](https://flutter.io/widgets/layout/).
class Column extends Flex {
/// Creates a vertical array of children.
......
......@@ -12,6 +12,9 @@ import 'framework.dart';
import 'image.dart';
import 'ticker_provider.dart';
// Examples can assume:
// Uint8List bytes;
/// An image that shows a [placeholder] image while the target [image] is
/// loading, then fades in the new image when it loads.
///
......@@ -46,14 +49,14 @@ import 'ticker_provider.dart';
/// different image. This is known as "gapless playback" (see also
/// [Image.gaplessPlayback]).
///
/// ## Sample code:
/// ## Sample code
///
/// ```dart
/// return new FadeInImage(
/// new FadeInImage(
/// // here `bytes` is a Uint8List containing the bytes for the in-memory image
/// placeholder: new MemoryImage(bytes),
/// image: new NetworkImage('https://backend.example.com/image.png'),
/// );
/// )
/// ```
class FadeInImage extends StatefulWidget {
/// Creates a widget that displays a [placeholder] while an [image] is loading
......
......@@ -32,6 +32,150 @@ import 'scrollable.dart';
/// that a [SingleChildScrollView] containing a [ListBody] or [Column] with
/// many children.
///
/// ## Sample code: Using [SingleChildScrollView] with a [Column]
///
/// Sometimes a layout is designed around the flexible properties of a
/// [Column], 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, 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 [SingleChildScrollView].
///
/// Simply doing so, however, usually results in a conflict between the [Column],
/// which typically tries to grow as big as it can, and the [SingleChildScrollView],
/// which provides its children with an infinite amount of space.
///
/// To resolve this apparent conflict, there are a couple of techniques, as
/// discussed below. These techniques should only be used when the content is
/// normally expected to fit on the screen, so that the lazy instantiation of
/// a sliver-based [ListView] or [CustomScrollView] is not expected to provide
/// any performance benefit. If the viewport is expected to usually contain
/// content beyond the dimensions of the screen, then [SingleChildScrollView]
/// would be very expensive.
///
/// ### 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],
/// the following technique can be used to provide the [Column] 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 (implicitly via
/// the constraints that the [SingleChildScrollView] sees, since viewports
/// typically grow to fit their maximum height constraint). Then, inside the
/// scroll view, a [ConstrainedBox] is used to set the minimum height of the
/// [Column].
///
/// 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] ends up
/// with some remaining space to allocate as specified by its
/// [Column.mainAxisAlignment] argument.
///
/// In this example, the children are spaced out equally, unless there's no
/// more room, in which case they stack vertically and scroll.
///
/// ```dart
/// new LayoutBuilder(
/// builder: (BuildContext context, BoxConstraints viewportConstraints) {
/// return SingleChildScrollView(
/// child: new ConstrainedBox(
/// constraints: new BoxConstraints(
/// minHeight: viewportConstraints.maxHeight,
/// ),
/// child: new Column(
/// mainAxisSize: MainAxisSize.min,
/// mainAxisAlignment: MainAxisAlignment.spaceAround,
/// children: <Widget>[
/// new Container(
/// // A fixed-height child.
/// color: Colors.yellow,
/// height: 120.0,
/// ),
/// new Container(
/// // Another fixed-height child.
/// color: Colors.green,
/// height: 120.0,
/// ),
/// ],
/// ),
/// ),
/// );
/// },
/// )
/// ```
///
/// 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).
/// The next section describes a technique for providing a maximum height constraint.
///
/// ### Expanding content to fit the viewport
///
/// The following example builds on the previous one. In addition to providing a
/// minimum dimension for the child [Column], an [IntrinsicHeight] widget is used
/// to force the column to be exactly as big as its contents. This constraint
/// combines with the [ConstrainedBox] constraints discussed previously to ensure
/// that the column becomes either as big as viewport, or as big as the contents,
/// whichever is biggest.
///
/// Both constraints must be used to get the desired effect. If only the
/// [IntrinsicHeight] was specified, then the column would not grow to fit the
/// entire viewport when its children were smaller than the whole screen. If only
/// the size of the viewport was used, then the [Column] would overflow if the
/// children were bigger than the viewport.
///
/// The widget that is to grow to fit the remaining space so provided is wrapped
/// in an [Expanded] widget.
///
/// ```dart
/// new LayoutBuilder(
/// builder: (BuildContext context, BoxConstraints viewportConstraints) {
/// return SingleChildScrollView(
/// child: new ConstrainedBox(
/// constraints: new BoxConstraints(
/// minHeight: viewportConstraints.maxHeight,
/// ),
/// child: new IntrinsicHeight(
/// child: new Column(
/// children: <Widget>[
/// new Container(
/// // A fixed-height child.
/// color: Colors.yellow,
/// height: 120.0,
/// ),
/// new Expanded(
/// // A flexible child that will grow to fit the viewport but
/// // still be at least as big as necessary to fit its contents.
/// child: new Container(
/// color: Colors.blue,
/// height: 120.0,
/// ),
/// ),
/// ],
/// ),
/// ),
/// ),
/// );
/// },
/// )
/// ```
///
/// This technique is quite expensive, as it more or less requires that the contents
/// of the viewport be laid out twice (once to find their intrinsic dimensions, and
/// once to actually lay them out). The number of widgets within the column should
/// therefore be kept small. Alternatively, subsets of the children that have known
/// dimensions can be wrapped in a [SizedBox] that has tight vertical constraints,
/// so that the intrinsic sizing algorithm can short-circuit the computation when it
/// reaches those parts of the subtree.
///
/// See also:
///
/// * [ListView], which handles multiple children in a scrolling list.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment