skills/flutter-adaptive-ui/references/layout-common-widgets.md

6.0 KiB

Common Layout Widgets

Container

Adds padding, margins, borders, background color, or other decorations to a widget.

Summary:

  • Add padding, margins, borders
  • Change background color or image
  • Contains a single child widget, but that child can be a Row, Column, or even the root of a widget tree

GridView

Lays widgets out as a two-dimensional list. GridView provides two pre-fabricated lists, or you can build your own custom grid. When a GridView detects that its contents are too long to fit the render box, it automatically scrolls.

Summary:

  • Lays widgets out in a grid
  • Detects when the column content exceeds the render box and automatically provides scrolling
  • Build your own custom grid, or use one of the provided grids:
    • GridView.count allows you to specify the number of columns
    • GridView.extent allows you to specify the maximum pixel width of a tile

Example using GridView.extent:

Widget _buildGrid() => GridView.extent(
  maxCrossAxisExtent: 150,
  padding: const EdgeInsets.all(4),
  mainAxisSpacing: 4,
  crossAxisSpacing: 4,
  children: _buildGridTileList(30),
);

List<Widget> _buildGridTileList(int count) =>
    List.generate(count, (i) => Image.asset('images/pic$i.jpg'));

ListView

[ListView][], a column-like widget, automatically provides scrolling when its content is too long for its render box.

Summary:

  • A specialized [Column][] for organizing a list of boxes
  • Can be laid out horizontally or vertically
  • Detects when its content won't fit and provides scrolling
  • Less configurable than Column, but easier to use and supports scrolling

Example:

Widget _buildList() {
  return ListView(
    children: [
      _tile('CineArts at the Empire', '85 W Portal Ave', Icons.theaters),
      _tile('The Castro Theater', '429 Castro St', Icons.theaters),
      _tile('Alamo Drafthouse Cinema', '2550 Mission St', Icons.theaters),
      const Divider(),
      _tile('K\'s Kitchen', '757 Monterey Blvd', Icons.restaurant),
      _tile('Emmy\'s Restaurant', '1923 Ocean Ave', Icons.restaurant),
      _tile('Chaiya Thai Restaurant', '272 Claremont Blvd', Icons.restaurant),
      _tile('La Ciccia', '291 30th St', Icons.restaurant),
    ],
  );
}

ListTile _tile(String title, String subtitle, IconData icon) {
  return ListTile(
    title: Text(
      title,
      style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 20),
    ),
    subtitle: Text(subtitle),
    leading: Icon(icon, color: Colors.blue[500]),
  );
}

Stack

Use [Stack][] to arrange widgets on top of a base widget—often an image. The widgets can completely or partially overlap the base widget.

Summary:

  • Use for widgets that overlap another widget
  • The first widget in the list of children is the base widget; subsequent children are overlaid on top of that base widget
  • A Stack's content can't scroll
  • You can choose to clip children that exceed the render box

Example:

Widget _buildStack() {
  return Stack(
    alignment: const Alignment(0.6, 0.6),
    children: [
      const CircleAvatar(
        backgroundImage: AssetImage('images/pic.jpg'),
        radius: 100,
      ),
      Container(
        decoration: const BoxDecoration(color: Colors.black45),
        child: const Text(
          'Mia B',
          style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          ),
        ),
      ),
    ],
  );
}

Card

A [Card][], from the Material library, contains related nuggets of information and can be composed of almost any widget, but is often used with [ListTile][]. Card has a single child, but its child can be a column, row, list, grid, or other widget that supports multiple children. By default, a Card shrinks its size to 0 by 0 pixels. You can use [SizedBox][] to constrain the size of a card.

Summary:

  • Implements a Material card
  • Used for presenting related nuggets of information
  • Accepts a single child, but that child can be a Row, Column, or other widget that holds a list of children
  • Displayed with rounded corners and a drop shadow
  • A Card's content can't scroll
  • From the Material library

Example:

Widget _buildCard() {
  return SizedBox(
    height: 210,
    child: Card(
      child: Column(
        children: [
          ListTile(
            title: const Text(
              '1625 Main Street',
              style: TextStyle(fontWeight: FontWeight.w500),
            ),
            subtitle: const Text('My City, CA 99984'),
            leading: Icon(Icons.restaurant_menu, color: Colors.blue[500]),
          ),
          const Divider(),
          ListTile(
            title: const Text(
              '(408) 555-1212',
              style: TextStyle(fontWeight: FontWeight.w500),
            ),
            leading: Icon(Icons.contact_phone, color: Colors.blue[500]),
          ),
          ListTile(
            title: const Text('costa@example.com'),
            leading: Icon(Icons.contact_mail, color: Colors.blue[500]),
          ),
        ],
      ),
    ),
  );
}

ListTile

Use [ListTile][], a specialized row widget from the Material library, for an easy way to create a row containing up to 3 lines of text and optional leading and trailing icons. ListTile is most commonly used in [Card][] or [ListView][], but can be used elsewhere.

Summary:

  • A specialized row that contains up to 3 lines of text and optional icons
  • Less configurable than Row, but easier to use
  • From the Material library