Flutter webでレスポンシブ対応

flutterはじめて１週間
大嫌いなhtml,cssをやらなくてもwebフロントが作れると聞いたのでflutter web中心に勉強中
flutter webだとレスポンシブ対応ってどうやるのと思って調べたのでそのまとめ
これが最適なのかどうかはまだ分かりません

# こんな感じ

<img src="https://media.giphy.com/media/S5bc1e0cQ5zJyY33LL/giphy.gif" width=70%>

# ソース

大雑把な考え方としては ` MediaQuery.of(context).size.width`ってので画面の横幅がわかるのでそれで場合分けして呼び出すWidgetを変えるだけです

## 表示させるwidgetたち

高さと色が固定のContainerを５つ

```widgets.dart
var widgetA = Container(
  height: 1500,
  color: Colors.red,
);

var widgetB = Container(
  height: 1000,
  color: Colors.green,
);

var widgetC = Container(
  height: 500,
  color: Colors.blue,
);

var widgetD = Container(
  height: 200,
  color: Colors.pink,
);

var widgetE = Container(
  height: 100,
  color: Colors.orange,
);
```

## ５種類のレイアウト

画面の種類を`xl`, `lg`, `md`, `sm`, `xs`の5つ定義して、それぞれの画面用にwidgetを用意して `widgetA`,`widgetB`,`widgetC`,`widgetD`,`widgetE`を配置


画面種類の定義だー！

```
enum ScreenType { xl, lg, md, sm, xs }
```



全部横並びだー！

```ExtraLargeScreen.dart
class ExtraLargeScreen extends StatelessWidget {
  const ExtraLargeScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("extra large"),
        ),
        body: SingleChildScrollView(
            child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              flex: 4,
              child: widgetA,
            ),
            Expanded(
              flex: 2,
              child: widgetB,
            ),
            Expanded(
              flex: 2,
              child: widgetC,
            ),
            Expanded(
              flex: 1,
              child: widgetD,
            ),
            Expanded(
              flex: 1,
              child: widgetE,
            ),
          ],
        )));
  }
}
```


右二つ縦並びだー！

```LargeScreen.dart
class LargeScreen extends StatelessWidget {
  const LargeScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("large"),
        ),
        body: SingleChildScrollView(
            child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
          Expanded(
            flex: 4,
            child: widgetA,
          ),
          Expanded(
            flex: 2,
            child: widgetB,
          ),
          Expanded(
            flex: 2,
            child: widgetC,
          ),
          Expanded(flex: 2, child: Column(children: [widgetD, widgetE]))
        ])));
  }
}
```


右三つ縦並びだー！

```MiddleScreen.dart
class MiddleScreen extends StatelessWidget {
  const MiddleScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("middle"),
        ),
        body: SingleChildScrollView(
            child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
          Expanded(
            flex: 5,
            child: widgetA,
          ),
          Expanded(
            flex: 3,
            child: widgetB,
          ),
          Expanded(
            flex: 2,
            child: Column(children: [widgetC, widgetD, widgetE]),
          ),
        ])));
  }
}
```

右四つ縦並びだー！

```SmallScreen.dart
class SmallScreen extends StatelessWidget {
  const SmallScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("small"),
        ),
        body: SingleChildScrollView(
            child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
          Expanded(
            flex: 6,
            child: widgetA,
          ),
          Expanded(
            flex: 4,
            child: Column(children: [widgetB, widgetC, widgetD, widgetE]),
          ),
        ])));
  }
}
```

全部縦並びだー！

```ExtraSmallScreen.dart
class ExtraSmallScreen extends StatelessWidget {
  const ExtraSmallScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("extra small"),
        ),
        body: SingleChildScrollView(
            child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
          Expanded(
            flex: 10,
            child:
                Column(children: [widgetA, widgetB, widgetC, widgetD, widgetE]),
          ),
        ])));
  }
}
```


## レスポンシブにするwidget

肝のレスポンシブに表示するwidget

```Responsive.dart

class Responsive extends StatefulWidget {
  Responsive({Key key}) : super(key: key);

  _ResponsiveState createState() => _ResponsiveState();
}

class _ResponsiveState extends State<Responsive> {
  //MediaQueryの横幅を5種類に場合分け
  get screenType {
    var width = MediaQuery.of(context).size.width;
    if (width > 1200) {
      return ScreenType.xl;
    } else if (width > 992) {
      return ScreenType.lg;
    } else if (width > 768) {
      return ScreenType.md;
    } else if (width > 544) {
      return ScreenType.sm;
    } else {
      return ScreenType.xs;
    }
  }

  @override
  Widget build(BuildContext context) {
    //スクリーンの種類でwidgetを出し分け
    switch (this.screenType) {
      case ScreenType.xl:
        return ExtraLargeScreen();
        break;
      case ScreenType.lg:
        return LargeScreen();
        break;
      case ScreenType.md:
        return MiddleScreen();
        break;
      case ScreenType.sm:
        return SmallScreen();
        break;
      case ScreenType.xs:
        return ExtraSmallScreen();
        break;
      default:
        break;
    }
  }
}
```


## ソースのまとめ
https://gist.github.com/sakiyamaK/8626f1ded606b67e29414647fd495182

# 感想
簡単！分かりやすい！
htmlやcssのレスポンシブのやり方を知らないからこれが簡単になってるのかも分からないけど！

# 参考
[Flutter公式](https://flutter.dev/docs/development/ui/layout/responsive)
[公式からのリンクで分かりやすかったやつ](https://medium.com/flutter-community/developing-for-multiple-screen-sizes-and-orientations-in-flutter-fragments-in-flutter-a4c51b849434)