(個人的に)Flutterでよく使用するWidgetをまとめてみた【サンプルコード付き】

# はじめに
Flutterを学習し始めて約3ヶ月(執筆時点)が経過し、これまで多く使用してきたWidgetをまとめてみようと思ったので記事にしました。
まだまだWidgetがたくさんあるので、この記事は随時更新していきます。
「もっと良いコードあるだろ」というご意見は百も承知ですが、ご了承ください。また、初投稿なので見づらい点があるかもしれません。
それぞれのWidgetの詳しい使い方はこの記事が書き終わったら別の記事にして出します。

# BasicWidgets早見表
|Widget|簡単な説明(翻訳)|使用例|
|:--|:--|:--|
|[Scaffold](https://api.flutter.dev/flutter/material/Scaffold-class.html)|基本的なマテリアルデザインのビジュアルレイアウト構造を実装します。<br>このクラスは、引き出しと下部シートを表示するためのAPIを提供します。|省略|
|[SafeArea](https://api.flutter.dev/flutter/widgets/SafeArea-class.html)|OSによる侵入を避けるために、十分なパディングによって子を挿入するウィジェット。|[SafeArea](#safearea)|
|[AppBar](https://api.flutter.dev/flutter/material/AppBar-class.html)|マテリアルデザインアプリバー。<br>アプリバーは、ツールバーと[TabBar](#tabbar-tabbarview)そしてFlexibleSpaceBar。|[AppBar](#appbar)|
|[TabBar](https://api.flutter.dev/flutter/material/TabBar-class.html)|タブの水平行を表示するマテリアルデザインウィジェット。<br>通常AppBar.bottomの[AppBar](#appbar)そしてTabBarViewとの結合|[TabBar](#tabbar-tabbarview)|
|[Text](https://api.flutter.dev/flutter/widgets/Text-class.html)|単一のスタイルのテキストの実行。|[Text](#text)|
|[Icon](https://api.flutter.dev/flutter/widgets/Icon-class.html)|Icons内のマテリアルの事前定義された IconDataなど、IconDataで記述されたフォントからのグリフで描画されたグラフィカルアイコンウィジェット。|[Icon](#icon)|
|[Image](https://api.flutter.dev/flutter/widgets/Image-class.html)|画像を表示するウィジェット。|[Image](#image)|
|[Align](https://api.flutter.dev/flutter/widgets/Align-class.html)|子供をそれ自体に揃え、オプションで自分自身をサイズ設定するウィジェット。|[Align](#align)|
|[Center](https://api.flutter.dev/flutter/widgets/Center-class.html)|子供を自分の中に集中させるウィジェット。|[Center](#center)|
|[Container](https://api.flutter.dev/flutter/widgets/Container-class.html)|一般的な絵画、配置、サイジングを組み合わせた便利なウィジェット。|[Container](#container)|
|[SizedBox](https://api.flutter.dev/flutter/widgets/SizedBox-class.html)|指定したサイズのボックス。|[SizedBox](#sizedbox)|
|[Padding](https://api.flutter.dev/flutter/widgets/Padding-class.html)|与えられたパディングで子供を差し込むウィジェット。|[Padding](#padding)|
|[Column](https://api.flutter.dev/flutter/widgets/Column-class.html)|子供を縦列に表示するウィジェット。|[Column](#column)|
|[Row](https://api.flutter.dev/flutter/widgets/Row-class.html)|子供を横列に表示するウィジェット。|[Row](#row)|
|[FittedBox](https://api.flutter.dev/flutter/widgets/FittedBox-class.html)|適合に応じて、その子をそれ自体の中でスケーリングおよび配置します。|[FittedBox](#fittedbox)|

# ButtonWidgets早見表
|Widget|簡単な説明(翻訳)|使用例|
|:--|:--|:--|
|[TextButton](https://api.flutter.dev/flutter/material/TextButton-class.html)|ツールバー、ダイアログ、または他のインラインにテキストボタンを使用する。|[TextButton](#textbutton)|
|[OutlinedButton](https://api.flutter.dev/flutter/material/OutlinedButton-class.html)|基本的に、枠線の付いたTextButtonです。|[OutlinedButton](#outlinedbutton)|
|[ElevatedButton](https://api.flutter.dev/flutter/material/ElevatedButton-class.html)|ElevatedButtonを使用して、それ以外の場合はほとんどフラットなレイアウトに次元を追加します。|[ElevatedButton](#elevatedbutton)|
|[FilledButton](https://api.flutter.dev/flutter/material/FilledButton-class.html)|FilledButtonは、FloatingActionButton の次に最も視覚的なインパクトがあります。|[FilledButton](#filledbutton)|
|[RawMaterialButton](https://api.flutter.dev/flutter/material/RawMaterialButton-class.html)|マテリアル、および InkWell ウィジェットに基づいてボタンを作成します。(もうすぐ廃止されるかも)|[RawMaterialButton](#rawmaterialbutton)|
|[IconButton](https://api.flutter.dev/flutter/material/IconButton-class.html)|IconButtonは一般的にAppBar.actionsフィールドで使用されますが、他の多くの場所でも使用できます。|[IconButton](#iconbutton)|
|[FloatingActionButton](https://api.flutter.dev/flutter/material/FloatingActionButton-class.html)|FloatingActionButtonは、アプリケーションで主要なアクションを促進するためにコンテンツの上に置く円形のアイコンボタンです。|[FloatingActionButton](#floatingactionbutton)|

# ViewWidgets早見表
|Widget|簡単な説明(翻訳)|使用例|
|:--|:--|:--|
|[Stack](https://api.flutter.dev/flutter/widgets/Stack-class.html)|ボックスの端を基準にして子を配置するウィジェット。|[Stack](#stack)|
|[Card](https://api.flutter.dev/flutter/material/Card-class.html)|わずかに丸みを帯びたコーナーと立面図の影を持つパネル。|[Card](#card)|
|[ListTile](https://api.flutter.dev/flutter/material/ListTile-class.html)|通常、テキストと先頭または末尾のアイコンを含む単一の固定高行。|[ListTile](#listtile)|
|[ListView](https://api.flutter.dev/flutter/widgets/ListView-class.html)|直線的に配置されたウィジェットのスクロール可能なリスト。|[ListView](#listview)|
|[GridView](https://api.flutter.dev/flutter/widgets/GridView-class.html)|ウィジェットのスクロール可能な2D配列。|[GridView](#gridview)|
|[SingleChildScrollView](https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html)|単一のウィジェットをスクロールできるボックス。|[SingleChildScrollView](#singlechildscrollview)|
|[ScrollBar](https://api.flutter.dev/flutter/material/Scrollbar-class.html)|スクロールバーを ScrollViewに追加するには、スクロールビューウィジェットをScrollbarウィジェットでラップします。|[ScrollBar](#scrollbar)|
|[CircularProgressIndicator](https://api.flutter.dev/flutter/material/CircularProgressIndicator-class.html)|マテリアルデザインの円形の進行状況インディケーター。アプリケーションがビジーであることを示すために回転します。|[CircularProgressIndicator](#circularprogressindicator)|
|[RefreshIndicator](https://api.flutter.dev/flutter/material/RefreshIndicator-class.html)|マテリアルの「スワイプして更新」イディオムをサポートするウィジェット。|[RefreshIndicator](#refreshindicator)|
|[Drawer](https://flutter.ctrnost.com/basic/navigation/drawer/)|DrawerはAndroidアプリでよく見るUIで、左からドロワーを表示し、メニューなどを配置するのに利用します。|[Drawer](#drawer)|
|[DataTable](https://api.flutter.dev/flutter/material/DataTable-class.html)|マテリアルデザインのDataTable|[DataTable](#datatable)|
|[Tooltip](https://api.flutter.dev/flutter/material/Tooltip-class.html)|マテリアルデザインのTooltip|[Tooltip](#tooltip)|
|[Divider](https://api.flutter.dev/flutter/material/Divider-class.html)|両側にパディングがある細い水平線|[Divider](#divider)|

# BasicWidgets
Flutterを使って開発していく上でめっちゃよく使われるWidgetをまとめました。

## SafeArea
スマホのOS側で表示されている画面上のステータスバーとか、画面下のホームバーを避けるようにPaddingを設けてくれるめっちゃ便利なWidgetです。
これ以降に紹介するWidgetにはSafeAreaを使用していませんが、使えばよかったと軽く後悔しています。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/59554369-710a-94ac-853d-59a5f54eae6a.png width=50% /><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/9ab3894a-6848-aed9-9ae5-6601d01b8dd2.png width=50% />

<details><summary>サンプルコード(SafeArea無し)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('SafeArea'),
      ),
      backgroundColor: Colors.red,
    );
  }
```
</details>

<details><summary>サンプルコード(SafeArea有り)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: const Text('SafeArea'),
        ),
        backgroundColor: Colors.red,
      ),
    );
  }
```
</details>

## AppBar
AppBarはアプリを作成する上で最も基本的なWidgetの1つで、マテリアルデザインを提供しています。
AppBarには様々なプロパティが存在していますが、基本的には以下の画像([こちら](https://api.flutter.dev/flutter/material/AppBar-class.html)から参照)にあるプロパティが使用されると思います。
<img src=https://flutter.github.io/assets-for-api-docs/assets/material/app_bar.png width=50% />

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/07a47b42-4d16-8d67-9ac2-96d796a37ca6.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: const Icon(Icons.dehaze_sharp),
        title: const Text('Title'),
        actions: const [
          Icon(Icons.more_vert),
        ],
        bottom: const PreferredSize(
          preferredSize: Size.fromHeight(30),
          child: Center(
            child: Text(
              'Bottom',
              style: TextStyle(fontSize: 20),
            ),
          ),
        ),
      ),
    );
  }
```
</details>

## TabBar, TabBarView
TabBarを使用する事で簡単にWidgetをタブで管理できるようになります。
実装にはDefaultTabController, TabBar, TabBarViewを使用します。

- DefaultTabController: 選択されたタブと表示するコンテンツを同期させる為に使用する。
- TabBar: ヘッダーに表示するタブ。AppBarのbottomプロパティに記述し、childrenプロパティにはタブ内で表示するTabWidgetを入れる。
- TabBarView: 各タブに対応して表示されるコンテンツ。

:::note warn
TabBarとTabBarViewは1対1で対応している為、それぞれの要素の数は同じかつ、DefaultTabControllerのlengthプロパティで指定する数と同じにしなければエラーになります。
:::

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/0081188c-9857-1193-e617-16b32674e665.gif width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      initialIndex: 0, // 初期選択タブ
      length: 3, // タブの数
      child: Scaffold(
        appBar: AppBar(
          title: const Text('TabBar'),
          bottom: const TabBar(
            tabs: [
              Tab(
                text: 'One',
              ),
              Tab(
                text: 'Two',
              ),
              Tab(
                text: 'Three',
              ),
            ],
          ),
        ),
        body: const TabBarView(
          children: [
            Center(
              child: Text('This page is one.'),
            ),
            Center(
              child: Text('This page is two.'),
            ),
            Center(
              child: Text('This page is three.'),
            ),
          ],
        ),
      ),
    );
  }
```
</details>

## Text
受け取った文字列を表示するだけのWidget。
この例では、Centerで囲んだだけでは画面中央に寄らない為、textAlignプロパティにTextAlign.centerを指定し、画面中央に表示させています。
styleプロパティにTextStyleを使用し、fontWeightで文字の太さ、fontSizeで文字の大きさ、colorで文字の色、backgroundColorで背景の色を指定しています。TextStyleには他にも多くのプロパティがある為、[こちら](https://api.flutter.dev/flutter/painting/TextStyle-class.html)を確認していただくと良いと思います。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/0bb457b0-6166-eb4c-a438-6277c9446edf.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Text'),
      ),
      body: const Center(
        child: Text(
          'This is the text widget.',
          textAlign: TextAlign.center,
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 40,
            color: Colors.red,
            backgroundColor: Colors.amberAccent,
          ),
        ),
      ),
    );
  }
```
</details>

## Icon
IconData型のアイコンを表示させるWidget。この例では、androidのアイコン、sizeプロパティに200、colorプロパティにgreenを指定して表示しています。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/7ee0708d-a118-d32b-f8ba-c024c4bd56ce.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Icon'),
      ),
      body: const Center(
        child: Icon(
          Icons.android,
          size: 200,
          color: Colors.green,
        ),
      ),
    );
  }
```
</details>

## Image
画像を表示する為に使用するWidget。
この例では、Image.networkを使用してインターネット上の画像を表示していますが、Image.assetを使用してアセット内に用意した画像を表示することも可能です。
他にもImage.memoryやImage.fileなどもありますが、基本的にはImage.networkとImage.assetで事足りると思います。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/f6cd1918-1e0b-d11d-e5a6-78d35f9c1c6c.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Image'),
      ),
      body: Center(
        child: Image.network(
          'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg',
        ),
      ),
    );
  }
```
</details>

## Align
childプロパティに指定した要素の位置を指定できるWidget。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/6d5a59af-5922-be7a-b781-abe7a1e2cc48.png width=30% /><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/a7400b6f-907d-f236-0fe7-1f487841875f.png width=30% /><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/f7479f4e-2438-e1b9-380d-e03fc3f852e9.png width=30% />

<details><summary>サンプルコード(TopLeft)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Align'),
      ),
      body: const Align(
        alignment: Alignment.topLeft,
        child: Text('Top Left'),
      ),
    );
  }
```
</details>

<details><summary>サンプルコード(Center)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Align'),
      ),
      body: const Align(
        alignment: Alignment.center,
        child: Text('Center'),
      ),
    );
  }
```
</details>

<details><summary>サンプルコード(BottomRight)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Align'),
      ),
      body: const Align(
        alignment: Alignment.bottomRight,
        child: Text('Bottom Right'),
      ),
    );
  }
```
</details>

## Center
Centerのchildプロパティに指定されたWidgetを中央に表示するだけのWidget。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/ebbf3571-9eec-aec4-7eef-2b0134e5dceb.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Center'),
      ),
      body: const Center(
        child: Text('This is the center widget.'),
      ),
    );
  }
```
</details>

## Container
Containerはpaddingやmargin、heightやwidthなど様々なプロパティを使用可能です。

:::note warn
単に高さや幅を取りたい場合はSizedBoxWidget、Paddingを取りたいだけならPaddingWidgetを使用するべきです。
:::

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/93cdc318-f7db-27e7-6340-8db464aff8b5.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Container'),
      ),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          decoration: BoxDecoration(
            color: Colors.red,
            border: Border.all(
              width: 2,
              color: Colors.black,
            ),
          ),
          child: const Align(
            alignment: Alignment.center,
            child: Text(
              'Red Box',
              style: TextStyle(
                color: Colors.white,
                fontSize: 40,
              ),
            ),
          ),
        ),
      ),
    );
  }
```
</details>

## SizedBox
SizedBoxのchildプロパティに指定した要素が持つ高さや幅を強制指定するWidget。
単にWidget間の余白を取る事にも使用される。

:::note info
子要素を高さいっぱい、幅いっぱいに表示する為にはSizedBox.expandを使用することができます。
:::

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/a9b16cb9-2d3a-b916-c702-d775b06f73d6.png width=50% /><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/68bffaf4-4452-0e60-0746-1582ac974c7b.png width=50% />


<details><summary>サンプルコード(高さ、幅指定)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Card'),
      ),
      body: const Center(
        child: SizedBox(
          height: 200,
          width: 300,
          child: Card(
            color: Colors.red,
            child: Align(
              alignment: Alignment.center,
              child: Text(
                'height: 200\nwidth: 300',
                style: TextStyle(color: Colors.white),
              ),
            ),
          ),
        ),
      ),
    );
  }
```
</details>

<details><summary>サンプルコード(SizedBox.expand)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('SizedBox'),
      ),
      body: const Center(
        child: SizedBox.expand(
          child: Card(
            color: Colors.red,
            child: Align(
              alignment: Alignment.center,
              child: Text(
                'SizedBox.expand',
                style: TextStyle(color: Colors.white),
              ),
            ),
          ),
        ),
      ),
    );
  }
```
</details>

## Padding
childプロパティに指定した要素に対してパディングを与えるWidget。
PaddingのpaddingプロパティにEdgeInsets.allを指定すれば全方向に、EdgeInsets.symmetricで上下方向に、EdgeInsets.onlyで上下左右方向にPaddingを設定可能です。
この例では、SizedBox.expandを使用して高さいっぱい、幅いっぱいに表示したCardに対してPaddingを設定しています。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/57e2e2bd-13a5-c2ba-43b1-cabe027e4a05.png width=30% /><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/fb40d22e-b781-512f-21cd-b4c21316ddd1.png width=30% /><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/3ec14da9-973a-5263-fb18-1d091ee6e27c.png width=30% />

<details><summary>サンプルコード(all)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Padding'),
      ),
      body: const Center(
        child: SizedBox.expand(
          child: Padding(
            padding: EdgeInsets.all(100),
            child: Card(
              color: Colors.red,
              child: Align(
                alignment: Alignment.center,
                child: Text(
                  'all: 100',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
```
</details>

<details><summary>サンプルコード(symmetric)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Padding'),
      ),
      body: const Center(
        child: SizedBox.expand(
          child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 30, vertical: 300),
            child: Card(
              color: Colors.red,
              child: Align(
                alignment: Alignment.center,
                child: Text(
                  'horizontal: 30\nvertical: 300',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
```
</details>

<details><summary>サンプルコード(only)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Padding'),
      ),
      body: const Center(
        child: SizedBox.expand(
          child: Padding(
            padding:
                EdgeInsets.only(top: 50, right: 100, bottom: 150, left: 200),
            child: Card(
              color: Colors.red,
              child: Align(
                alignment: Alignment.center,
                child: Text(
                  'top: 50\nright: 100\nbottom: 150\nleft: 200',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
```
</details>

## Column
Columnのchildrenプロパティに渡されたWidget型の配列を1つずつ縦方向に表示するWidget。
また、mainAxisAlignmentプロパティにstart、center、endなどを指定する事で縦方向に表示する位置を調整することができます（詳しくは[こちら](https://api.flutter.dev/flutter/rendering/MainAxisAlignment.html)をご覧ください）。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/69136b14-def2-39b7-93a3-8e8a2d88108c.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Column'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Text(
              'child1',
              style: TextStyle(fontSize: 40),
            ),
            Text(
              'child2',
              style: TextStyle(fontSize: 40),
            ),
            Text(
              'child3',
              style: TextStyle(fontSize: 40),
            ),
            Text(
              'child4',
              style: TextStyle(fontSize: 40),
            ),
            Text(
              'child5',
              style: TextStyle(fontSize: 40),
            ),
          ],
        ),
      ),
    );
  }
```
</details>

## Row
Rowのchildrenプロパティに渡されたWidget型の配列を1つずつ横方向に表示するWidget。
また、mainAxisAlignmentプロパティにstart、center、endなどを指定する事で横方向に表示する位置を調整することができます（詳しくは[こちら](https://api.flutter.dev/flutter/rendering/MainAxisAlignment.html)をご覧ください）。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/6fc55e64-8d14-ea81-3047-77f58d02a248.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Row'),
      ),
      body: Center(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: const [
            Text(
              'child1',
              style: TextStyle(fontSize: 40),
            ),
            Text(
              'child2',
              style: TextStyle(fontSize: 40),
            ),
            Text(
              'child3',
              style: TextStyle(fontSize: 40),
            ),
          ],
        ),
      ),
    );
  }
```
</details>

## FittedBox
Flutterで開発を行っていると、以下のように画面外に要素がはみ出してエラーとなる事がある。このエラーに対してFittedBoxを使用する事でchildプロパティに指定した要素の大きさをよしなにしてくれる。

**エラーの例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/ba12059b-2f4d-fdf6-c1b1-2a9f7adb5296.png width=50% />

<details><summary>エラーとなるサンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('FittedBox'),
      ),
      body: Center(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: const [
            Text(
              'child1',
              style: TextStyle(fontSize: 40),
            ),
            Text(
              'child2',
              style: TextStyle(fontSize: 40),
            ),
            Text(
              'child3',
              style: TextStyle(fontSize: 40),
            ),
            Text(
              'child4',
              style: TextStyle(fontSize: 40),
            ),
          ],
        ),
      ),
    );
  }
```
</details>

このエラーを改善する為にFittedBoxのchildプロパティにRowを指定することで、Rowの子要素が画面外にはみ出すのを防いでくれる。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/2b5a6aad-6775-3658-bc54-be06a7f0f0d5.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('FittedBox'),
      ),
      body: Center(
        child: FittedBox(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: const [
              Text(
                'child1',
                style: TextStyle(fontSize: 40),
              ),
              Text(
                'child2',
                style: TextStyle(fontSize: 40),
              ),
              Text(
                'child3',
                style: TextStyle(fontSize: 40),
              ),
              Text(
                'child4',
                style: TextStyle(fontSize: 40),
              ),
            ],
          ),
        ),
      ),
    );
  }
```
</details>

# ButtonWidgets
ボタン類をまとめました。様々な種類のボタンがありますが、それぞれが持つプロパティにほとんど差がないので、1つのコードにまとめました。

## TextButton
childプロパティに指定したTextをそのままボタンとして扱うことができるWidget。

## OutlinedButton
TextButtonに枠線を追加したWidget。

## ElevatedButton
最も基本的なボタンWidget。

## FilledButton
ElevatedButtonを角丸にしたWidget。

## RawMaterialButton
Cardにボタン機能をつけたようなボタンWidget。(公式サイトで「もうすぐ廃止する予定がある」と記載されていた)

## IconButton
Iconにボタン機能をつけたようなボタンWidget。

## FloatingActionButton
ElevatedButtonを円形にしたようなボタンWidget。ScaffoldのfloatingActionButtonプロパティに使用することも可能。

**デモ**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/8181e290-1fc2-9a22-f8b4-c36f0c501699.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Buttons'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              onPressed: () {},
              child: const Text('TextButton'),
            ),
            OutlinedButton(
              onPressed: () {},
              child: const Text('OutlinedButton'),
            ),
            ElevatedButton(
              onPressed: () {},
              child: const Text('ElevatedButton'),
            ),
            FilledButton(
              onPressed: () {},
              child: const Text('FilledButton'),
            ),
            RawMaterialButton(
              onPressed: () {},
              fillColor: Colors.white,
              elevation: 5,
              child: const Text('RawMaterialButton'),
            ),
            IconButton(
              onPressed: () {},
              icon: const Icon(Icons.add),
            ),
            FloatingActionButton(
              onPressed: () {},
              child: const Icon(Icons.add),
            ),
          ],
        ),
      ),
    );
  }
```
</details>

# ViewWidgets
見た目(UI)に関係するWidgetをまとめました。

## Stack
Stackのchildrenプロパティに渡されたWidget型の配列を重ねて表示させるWidget。
配列のインデックスが小さいものが重ねた時に下に来ます。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/12b85ee9-6de7-03d7-fe87-09b1bb342eaa.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Stack'),
      ),
      body: Center(
        child: Stack(
          children: [
            Container(
              height: 200,
              width: 200,
              color: Colors.blue,
            ),
            Container(
              height: 150,
              width: 150,
              color: Colors.red,
            ),
            Container(
              height: 100,
              width: 100,
              color: Colors.yellow,
            ),
            Container(
              height: 50,
              width: 50,
              color: Colors.green,
            ),
          ],
        ),
      ),
    );
  }
```
</details>

## Card
要素を立体的に表示させる事ができるWidget。

:::note info
Cardの高さと幅を指定するには、CardをSizedBoxで囲んでheightとwidthを指定すればOKです。
:::

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/2b59febe-88ed-fa9b-17e8-c1b9fd2906c9.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Card'),
      ),
      body: const Center(
        child: SizedBox(
          height: 100,
          width: 200,
          child: Card(
            elevation: 10,
            child: Align(
              alignment: Alignment.center,
              child: Text('Card'),
            ),
          ),
        ),
      ),
    );
  }
```
</details>

## ListTile
アプリでよく見かけるリスト項目を提供するWidget。

:::note info
ListTileをCardで囲むといい感じになります。
:::

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/0bda8271-4339-1f58-190a-828fab12850c.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ListTile'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: const [
          ListTile(
            leading: Icon(Icons.add),
            title: Text('ListTile'),
            trailing: Icon(Icons.more_vert),
            tileColor: Colors.black12,
          ),
          Card(
            elevation: 5,
            child: ListTile(
              leading: Icon(Icons.add),
              title: Text('ListTile in Card'),
              trailing: Icon(Icons.more_vert),
              tileColor: Colors.redAccent,
            ),
          ),
        ],
      ),
    );
  }
```
</details>

## ListView
スクロールする事が可能なWidget。
垂直方向にスクロールするのがデフォルトだが、scrollDirectionプロパティにAxis.horizontalを指定する事で水平方向にスクロールできます。
下から並べるなら、reverseプロパティにtrueを指定します。
単なるListViewよりもListView.builderを使用する事の方が多い気がします。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/48f44a22-e316-c7a1-e2cb-46aeea4c4a97.gif width=50% /><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/b48d1458-22df-4efe-d331-c4f912ea426c.gif width=50% />

<details><summary>サンプルコード(ListView)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ListView'),
      ),
      body: ListView(
        children: const [
          ListTile(
            leading: Icon(Icons.add),
            title: Text('List0'),
            trailing: Icon(Icons.more_vert),
            tileColor: Colors.amber,
          ),
          ListTile(
            leading: Icon(Icons.add),
            title: Text('List1'),
            trailing: Icon(Icons.more_vert),
            tileColor: Colors.greenAccent,
          ),
          ListTile(
            leading: Icon(Icons.add),
            title: Text('List2'),
            trailing: Icon(Icons.more_vert),
            tileColor: Colors.blue,
          ),
          ListTile(
            leading: Icon(Icons.add),
            title: Text('List3'),
            trailing: Icon(Icons.more_vert),
            tileColor: Colors.redAccent,
          ),
        ],
      ),
    );
  }
```
</details>

<details><summary>サンプルコード(ListView.builder)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    const List<Color> colors = [
      Colors.purpleAccent,
      Colors.cyanAccent,
      Colors.pinkAccent,
      Colors.yellowAccent
    ];

    return Scaffold(
      appBar: AppBar(
        title: const Text('ListView.builder'),
      ),
      body: ListView.builder(
        itemCount: colors.length,
        itemBuilder: (context, index) => ListTile(
          leading: const Icon(Icons.add),
          title: Text('List$index'),
          trailing: const Icon(Icons.more_vert),
          tileColor: colors[index],
        ),
      ),
    );
  }
```
</details>

## GridView
- スクロールする事が可能なWidget。
- 垂直方向にスクロールするのがデフォルトだが、scrollDirectionプロパティにAxis.horizontalを指定する事で水平方向にスクロールできます。
- 下から並べるなら、reverseプロパティにtrueを指定します。
- mainAxisSpacingプロパティで垂直方向の要素のスペース、crossAxisSpacingプロパティで水平方向同士の要素のスペースを確保できます。
- crossAxisCountプロパティで並べる要素数を指定できます。
- GridView.countよりもGridView.builderを使用する事の方が多い気がします。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/52d78874-05c3-9f01-b6e1-ce4cc4db24dd.gif width=50% /><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/a0699b22-38b5-d6ea-4cd1-0255d11df965.gif width=50% />

<details><summary>サンプルコード(GridView.count)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GridView.builder'),
      ),
      body: GridView.count(
        mainAxisSpacing: 10,
        crossAxisSpacing: 10,
        crossAxisCount: 2,
        children: [
          Container(
            color: Colors.amber,
            child: const Center(
              child: Text('Grid0'),
            ),
          ),
          Container(
            color: Colors.red,
            child: const Center(
              child: Text('Grid1'),
            ),
          ),
          Container(
            color: Colors.red,
            child: const Center(
              child: Text('Grid2'),
            ),
          ),
          Container(
            color: Colors.amber,
            child: const Center(
              child: Text('Grid3'),
            ),
          ),
          Container(
            color: Colors.amber,
            child: const Center(
              child: Text('Grid4'),
            ),
          ),
          Container(
            color: Colors.red,
            child: const Center(
              child: Text('Grid5'),
            ),
          ),
          Container(
            color: Colors.red,
            child: const Center(
              child: Text('Grid6'),
            ),
          ),
          Container(
            color: Colors.amber,
            child: const Center(
              child: Text('Grid7'),
            ),
          ),
        ],
      ),
    );
  }
```
</details>

<details><summary>サンプルコード(GridView.builder)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GridView.builder'),
      ),
      body: GridView.builder(
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          mainAxisSpacing: 10,
          crossAxisSpacing: 10,
          crossAxisCount: 2,
        ),
        itemCount: 8,
        itemBuilder: (context, index) => Container(
          color: index % 4 == 1 || index % 4 == 2
              ? Colors.green
              : Colors.pinkAccent,
          child: Center(
            child: Text('Grid$index'),
          ),
        ),
      ),
    );
  }
```
</details>

## SingleChildScrollView
普段はスクロール不可能なWidgetをスクロールさせたい時に使用します。
**A RenderFlex overflowed関係のエラーは大体SingleChildScrollViewで囲めば解決します。**
~~いい例が思い浮かばなかったので雑な例です~~

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/984985ab-0c5a-743c-9e9d-186e1f1d55dd.png width=50% /><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/54ca51de-2dcf-71a1-a2c8-905e7614d0c1.gif width=50% />

<details><summary>サンプルコード(エラーになります)</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('SingleChildScrollView'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(10),
        child: Column(
          children: [
            for (int i = 0; i < 100; i++) ...{
              Container(
                height: 50,
                decoration: BoxDecoration(
                  border: Border.all(width: 1),
                ),
                child: Align(
                  alignment: Alignment.center,
                  child: Text('child$i'),
                ),
              ),
            },
          ],
        ),
      ),
    );
  }
```
</details>

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('SingleChildScrollView'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(10),
        child: SingleChildScrollView(
          child: Column(
            children: [
              for (int i = 0; i < 100; i++) ...{
                Container(
                  height: 50,
                  decoration: BoxDecoration(
                    border: Border.all(width: 1),
                  ),
                  child: Align(
                    alignment: Alignment.center,
                    child: Text('child$i'),
                  ),
                ),
              },
            ],
          ),
        ),
      ),
    );
  }
```
</details>

## ScrollBar
ScrollViewWidget(ListView, GridView, SingleChildScrollViewなど)をScrollBarで囲む事でScrollBarを表示させる事ができる。
thumbVisibilityプロパティでScrollBarを常に表示させるか否か、thicknessプロパティでScrollBarの太さを変更できたりする。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/1164d5fe-f9e2-e3cd-f03f-6155f9c4ea45.gif width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ScrollBar'),
      ),
      body: Scrollbar(
        thumbVisibility: true,
        thickness: 10,
        radius: const Radius.circular(10),
        child: ListView.builder(
          itemCount: 100,
          itemBuilder: (context, index) => ListTile(
            title: Text('List$index'),
            trailing: const Icon(Icons.more_vert),
          ),
        ),
      ),
    );
  }
```
</details>

## CircularProgressIndicator
よくあるクルクルを表示するWidget

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/411ca615-9d31-2f97-fce9-67a0e1a2793d.gif width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('CircularProgressIndicator'),
      ),
      body: const Center(
        child: CircularProgressIndicator(),
      ),
    );
  }
```
</details>

## RefreshIndicator
画面を下に引っ張った時に表示する読み込み中Widget
onRefreshプロパティにFuture\<void\>の関数を渡すが、その関数にDBへの操作など読み込みたい処理を記述して使用する

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/8917b15d-c206-5a2d-731f-826996ba3619.gif width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    Future<void> refreshFn() {
      return Future.delayed(
        const Duration(seconds: 0),
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: const Text('RefreshIndicator'),
      ),
      body: RefreshIndicator(
        onRefresh: refreshFn,
        child: ListView.builder(
          itemCount: 50,
          itemBuilder: (context, index) => ListTile(
            title: Text('List$index'),
          ),
        ),
      ),
    );
  }
```
</details>

## Drawer
Androidアプリでよく見られる左からメニューを表示するWidget。
ScaffoldのdrawerプロパティにDrawerを入れ、DrawerHeaderやListViewを組み合わせることで使用できます。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/f88b5ffe-bce5-2c42-4c5f-d794d08e72a1.png width=50% />

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Drawer'),
      ),
      drawer: Drawer(
        child: ListView(
          children: const [
            DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
              child: Text('This is header'),
            ),
            ListTile(
              title: Text('Item1'),
              trailing: Icon(Icons.arrow_forward),
            ),
            ListTile(
              title: Text('Item2'),
              trailing: Icon(Icons.arrow_forward),
            ),
          ],
        ),
      ),
    );
  }
```
</details>

## DataTable
よくある表を作成することができるWidget。
DataColumnとcellsの個数が異なるとエラーとなります。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/cface3ec-d53a-21b6-d7fd-fe2dd93be549.png width=50% >

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('DataTable'),
      ),
      body: Center(
        child: DataTable(
          columns: const [
            DataColumn(
              label: Text(
                'Name',
                style: TextStyle(
                  fontStyle: FontStyle.italic,
                ),
              ),
            ),
            DataColumn(
              label: Text(
                'Age',
                style: TextStyle(
                  fontStyle: FontStyle.italic,
                ),
              ),
            ),
            DataColumn(
              label: Text(
                'Job',
                style: TextStyle(
                  fontStyle: FontStyle.italic,
                ),
              ),
            ),
          ],
          rows: const [
            DataRow(
              cells: [
                DataCell(Text('Smith')),
                DataCell(Text('29')),
                DataCell(Text('Police')),
              ],
            ),
            DataRow(
              cells: [
                DataCell(Text('Emily')),
                DataCell(Text('20')),
                DataCell(Text('Artist')),
              ],
            ),
            DataRow(
              cells: [
                DataCell(Text('Saki')),
                DataCell(Text('34')),
                DataCell(Text('Teacher')),
              ],
            ),
          ],
        ),
      ),
    );
  }
```
</details>

## Tooltip
長押しした時に出現するヒント(tip)。

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/1ea2ab53-bc24-8d49-3de2-05cd1887f39d.png width=50% >

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Tooltip'),
      ),
      body: const Center(
        child: Tooltip(
          message: 'Press and hold.',
          child: Text('Long press here.'),
        ),
      ),
    );
  }
```
</details>

## Divider
線を引くWidget。Widget同士を分けるのに使用される

**使用例**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444597/b2ec71c7-7207-e12c-b786-989f2f5a94fd.png width=50% >

<details><summary>サンプルコード</summary>

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Divider'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Container(
            color: Colors.red,
            height: 100,
            width: double.infinity,
            child: const Align(
              alignment: Alignment.center,
              child: Text(
                '上',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 40,
                ),
              ),
            ),
          ),
          const Divider(
            color: Colors.black,
            thickness: 5,
          ),
          Container(
            color: Colors.blue,
            height: 100,
            width: double.infinity,
            child: const Align(
              alignment: Alignment.center,
              child: Text(
                '下',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 40,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
```
</details>