FlutterでBottomSheetの高さを変更する


# 基本のおさらい

FlutterでBottomSheetを表示する際は、`showBottomsheet`メソッド、もしくは`showModalBottomSheet`を用いて表示をすると思います。

### showBottomsheetの例

https://api.flutter.dev/flutter/material/ScaffoldState/showBottomSheet.html


```dart
Scaffold.of(context).showBottomSheet<void>(
  (BuildContext context) {
    return Container(
      height: 200,
      color: Colors.amber,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            const Text('BottomSheet'),
            ElevatedButton(
              child: const Text('Close BottomSheet'),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
    );
  },
);
```

### showModalBottomSheetの例
```Dart
showModalBottomSheet<dynamic>(
  context: context,
  builder: (BuildContext context) {
    return Container(
      height: 100,
      width: MediaQuery.sizeOf(context).width,
      decoration: const BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(16),
          topRight: Radius.circular(16),
        ),
      ),
    );
  },
);
```

記載の面でも、`showModalBottomSheet`の方が使いやすいためそちらを中心に進めていきます。

# 本題：bottomSheetの高さ調整について

では、まず上記のサンプルコードを定義します。
一旦全体のコードを提示します。

```Dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  Future<void> showBottomSheetDemo(BuildContext context) {
    return showModalBottomSheet<dynamic>(
      context: context,
      builder: (BuildContext context) {
        return Container(
          height: 100,
          width: MediaQuery.sizeOf(context).width,
          decoration: const BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(16),
              topRight: Radius.circular(16),
            ),
          ),
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
        body: const Center(
          child: Text(
            'Hello, world!',
            style: TextStyle(fontSize: 24),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            showBottomSheetDemo(context);
          },
          child: const Icon(Icons.add),
        ));
  }
}
```

上記のアプリの、FloatingActionButtonをタップすると以下のように高さ100のボトムシートが表示されます。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735195/61d639c6-11e0-a84f-42bd-f5aed94c3ebd.png" width="250" >


ちなみに、Flutterではメディアクエリを用いて簡易的に画面の高さや幅が取得できます。
今回はiPhone14のシュミレーターで検証していますが、iPhone14の高さは`844.0`でした。

```dart
print(MediaQuery.sizeOf(context).height.toString());
// flutter: 844.0
```

なので、今度は画面いっぱいに広がるように`height: 844`と指定してみます。

```diff_dart
Future<void> showBottomSheetDemo(BuildContext context) {
  return showModalBottomSheet<dynamic>(
    context: context,
    builder: (BuildContext context) {
      return Container(
-       height: 100,
+       height: 844,
        width: MediaQuery.sizeOf(context).width,
        decoration: const BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(16),
            topRight: Radius.circular(16),
          ),
        ),
      );
    },
  );
}
```

では、もう一度表示させた結果を添付します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735195/37189b93-9ff8-bff5-6bf9-2876948c6b9e.png" width="250" >

あれ？半分くらいの高さにしかなりませんね。。
そうです、Flutterのボトムシートは、一工夫しないと**50%の高さで制御**されてしまいます。

## 対処法

ボトムシートの高さが50%未満の場合はこういった考慮は不要ですが、50%以上超える場合は以下のようにパラメーターを設定してください。


```diff_dart
Future<void> showBottomSheetDemo(BuildContext context) {
  return showModalBottomSheet<dynamic>(
    context: context,
+   isScrollControlled: true,
+   backgroundColor: Colors.transparent, // これはついで
    builder: (BuildContext context) {
      return Container(
-        height: 844,
+        height: 800, // 最大高さより少し小さめを設定
        width: MediaQuery.sizeOf(context).width,
        decoration: const BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(16),
            topRight: Radius.circular(16),
          ),
        ),
      );
    },
  );
```

基本的に、以下の`isScrollControlled`が設定してあれば高さの調整が可能です。
`backgroundColor`は、未指定の場合MaterialAppで定義したthemeの色が自動で適応されてしまいUIの阻害になりうるため、透明（`transparent`)で指定しておくと無難でしょう。

```Dart
isScrollControlled: true,
backgroundColor: Colors.transparent,
```