【Flutter】SafeAreaの使い方

私自身Flutterに触れて7ヶ月ほどになるのですが、独学期間が長かった+よく理解せずFlutterに触れていたため、たまに「自分はこのWidgetを正しく使いこなせているのだろうか？」と不安になることがあります。Flutterは「Widgetをどれだけ知っているか」によってアプリケーションの出来が全く違う（というのを何処かで見た気がします）という点があるため、公式の [Flutter Widget of the week](https://www.youtube.com/playlist?list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG)で紹介されているWidgetを一から学習していくことに決めました。

また、ただ動画を視聴しているだけだと覚えが悪い自分ではすぐ忘れてしまいそうなので、アウトプットがてらQiitaを書いていくことしました。

挫折しないよう、
**○基本的なことのみ**
**○気分が向いたら**
で書いていこうと思います。


今回は**SafeArea**の使い方について解説していきます。

## 対象読者
○Flutter初学者
○SafeAreaの基本的な使い方を学びたい人

上記の方におすすめです。

では、解説していきます。

## 公式
**公式ドキュメント**
https://api.flutter.dev/flutter/widgets/SafeArea-class.html

**公式Youtube**

https://youtu.be/lkF0TQJO0bA

## SafeAreaとは

SafeAreaとはノッチ（画面上部の黒い窪み）やホームバーでWidgetが隠れてしまわないように、適切に空白を開けてくれるWidgetです。

例えば下記のようなサンプルを見ると、

```main.dart
Scaffold(
      body: ListView.builder(
        itemBuilder: (BuildContext context, int index) {
          return const Center(
            child: Text('Flutter'),
          );
        },
      ),
    );
```

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466417/1aecb3b3-6d44-c9f5-6cd3-77dbd922ae44.png' width='300'>

写真のようにFlutterという文字が見切れてしまっています。
最近のスマートフォンではノッチがあるものが多いため、これでは何かと不便です。
そこで**SafeArea**が活躍します。先ほどのコードにSafeAreaを追加してみると、

```main.dart
Scaffold(
// SafeAreaを追加
      body: SafeArea(
        child: ListView.builder(
          itemBuilder: (BuildContext context, int index) {
            return const Center(
              child: Text('Flutter'),
            );
          },
        ),
      ),
    );
```

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466417/ef35dd1f-6e4c-a41d-ab84-f1a255bd401f.png' width='300'>

こんな感じでよしなに空白を開けてくれます。
公式でも述べている通り、SafeAreaの中身を見てみると画面サイズを`MediaQuery`で取得しているため、端末サイズ関係なしに綺麗に適用されているみたいですね。

```dart
  @override
  Widget build(BuildContext context) {
    assert(debugCheckHasMediaQuery(context));
    final MediaQueryData data = MediaQuery.of(context); // MediaQueryで画面サイズを把握
    EdgeInsets padding = data.padding;
```



##主な使い方

SafeAreaには
○top
○bottom
○left
○right
○maintainBottomViewPadding
というプロパティがあります。
bool値を指定することによって使用を切り替えることができます。

`top`、`bottom`、`left`、`right`はその名の通り、上下左右に適用させる部分を個別に指定することができます。
こちらはSafeAreaを使用するとデフォルトでは全て`true`になっているみたいです。

```dart
Scaffold(
      body: SafeArea(
        top: true,
        bottom: true,
        left: true,
        right: true,
        child: ListView.builder(
          itemBuilder: (BuildContext context, int index) {
            return const Center(
              child: Text('Flutter'),
            );
          },
        ),
      ),
```

例えば上記のコードの`bottom`をfalseに変えた場合は、

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466417/c5bcbf85-0fdc-1b0b-7cc6-75b0ce33a2da.png' width='300'>

こんな感じで画面下部だけSafeAreaの適用が外れます。


最後に、`maintainBottomViewPadding`について、公式では下記のように書かれていました。

> For example, if there is an onscreen keyboard displayed above the SafeArea, the padding can be maintained below the obstruction rather than being consumed. This can be helpful in cases where your layout contains flexible widgets, which could visibly move when opening a software keyboard due to the change in the padding value. Setting this to true will avoid the UI shift.

どうやら`maintainBottomViewPadding`を`true`にしていると、例えば、キーボードを表示したときのUIのズレを防ぐことができる？みたいです。
ただ、実際にどういう場面で使用されるか自分でもわかっていないため、詳しい方がいましたら教えていただけますと幸いです。......(基本的には上下左右の指定だけで事足りそう)


## 感想
こんな感じでFlutter Widget of the weekの動画を見たら実装してQiitaを書いてアウトプットしていく形で行こうかと思います。
自分のアウトプット用に書いていますが、どなたかの参考になれば嬉しいです。