build method

  1. @override
Widget build(
  1. BuildContext context
)
override

Describes the part of the user interface represented by this widget.

The framework calls this method when this widget is inserted into the tree in a given BuildContext and when the dependencies of this widget change (e.g., an InheritedWidget referenced by this widget changes). This method can potentially be called in every frame and should not have any side effects beyond building a widget.

The framework replaces the subtree below this widget with the widget returned by this method, either by updating the existing subtree or by removing the subtree and inflating a new subtree, depending on whether the widget returned by this method can update the root of the existing subtree, as determined by calling Widget.canUpdate.

Typically implementations return a newly created constellation of widgets that are configured with information from this widget's constructor and from the given BuildContext.

The given BuildContext contains information about the location in the tree at which this widget is being built. For example, the context provides the set of inherited widgets for this location in the tree. A given widget might be built with multiple different BuildContext arguments over time if the widget is moved around the tree or if the widget is inserted into the tree in multiple places at once.

The implementation of this method must only depend on:

If a widget's build method is to depend on anything else, use a StatefulWidget instead.

See also:

  • StatelessWidget, which contains the discussion on performance considerations.

Implementation

@override
Widget build(BuildContext context) {
  var canvas = shot.canvas;
  return Container(
    width: canvas.logicalWidth,
    height: canvas.logicalHeight,
    color: ground,
    child: Column(
      children: [
        // The band is laid out whenever there are words for it, and not
        // otherwise. Reserving it either way keeps a mixed set's devices at
        // one height — but a set with *no* headlines anywhere is the common
        // case for a project that declared no frame, and there it is a
        // sixth of the canvas of nothing, with the device floating below it
        // looking like a mistake. A project mixing the two passes an empty
        // string for the ones it wants blank.
        SizedBox(
          height: canvas.logicalHeight * (headline == null ? 0.07 : 0.16),
          child: headline == null
              ? null
              : Padding(
                  padding: EdgeInsets.symmetric(
                    horizontal: canvas.logicalWidth * 0.09,
                  ),
                  child: Center(
                    child: Text(
                      headline!,
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        color: ink,
                        fontSize: canvas.logicalWidth * 0.072,
                        height: 1.2,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),
                ),
        ),
        // Bleeding off the bottom edge, which is the standard composition
        // because it uses a very tall canvas without leaving the device
        // stranded in the middle of it.
        //
        // Whether it *does* bleed is a race between two numbers, and the
        // margins below are what settle it: the body is scaled to the width
        // its padding leaves, so a narrower pair of margins makes it taller.
        // A phone is taller than the space under the band on Play's canvas —
        // which is the only place this frame is forced — so at these values
        // it overflows and the overflow is clipped away. The headline-less
        // pair is the tighter of the two on purpose: with no caption to make
        // room for there is more width to spend, and at the 0.09 it used to
        // share with the caption case the body came out 16 logical pixels
        // *short* of the space — no bleed, and 42 physical pixels of ground
        // under the device, which is the stranded look this composition
        // exists to avoid, arrived at from the other side. What was actually
        // drawn there was worse still, and the `minHeight` below is that
        // half: the floor stretched those 16 pixels back out of the picture.
        //
        // A device shorter than the space cannot bleed at any margin — that
        // would mean scaling past the canvas width and cropping the picture
        // sideways, which is the one thing a store screenshot must not do.
        // There it sits at the top of the space, and `defaultStoreFrame`
        // keeps it out of that case by handing those targets a
        // [PlainStoreFrame] instead.
        Expanded(
          child: Padding(
            padding: EdgeInsets.symmetric(
              horizontal:
                  canvas.logicalWidth * (headline == null ? 0.07 : 0.11),
            ),
            child: ClipRect(
              child: OverflowBox(
                alignment: Alignment.topCenter,
                // Both ends, and `minHeight` is the load-bearing one.
                // `OverflowBox` inherits whichever bounds it is not given,
                // and the bound here comes from an `Expanded` — which is
                // tight. So a body shorter than the space was being
                // stretched to fill it, and [_Body] paints the capture with
                // `BoxFit.fill`: the picture came out squashed by however
                // much it was short, silently, which is the one failure a
                // store screenshot cannot survive. Releasing the floor lets
                // a short body stay its own height and sit at the top of the
                // space — visibly imperfect, and imperfect beats wrong.
                minHeight: 0,
                maxHeight: double.infinity,
                child: _Body(
                  shot: shot,
                  radius: _radius,
                  edge: ink.withValues(alpha: 0.16),
                ),
              ),
            ),
          ),
        ),
      ],
    ),
  );
}