Flutter Textフォームに入力中、入力内容が重なって見えない場合

`resizeToAvoidBottomInset`を使用すると`widget`と`body`が重ならないようにキーボード部分を押し上げてくれて上手くいくのですが、
![スクリーンショット 2022-10-05 13.19.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/bf58afc8-04a4-bdb4-e157-450139d203c7.png)
増やした入力欄や下段にレイアウトした`Button`などの影響により、
![スクリーンショット 2022-10-05 13.58.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/58b6b389-a3a9-caaf-9668-cbb7acd51650.png)
フォームの入力部分に`Stack`されてしまい何を入力しているのかわからなくなってしまった場合の対処法です。位置調整に`Hooks`の`useEffect`を使い毎回呼ばれるようにしてあります。
```dart
 // キーボードの高さを取得してbottomSpaceにいれる
    final bottomSpace = MediaQuery.of(context).viewInsets.bottom;
    // SingleChildScrollViewを管理
    final scrollController = ScrollController();
    useEffect(() {
      // ビルド直後にscrollControllerの位置を調整
      WidgetsBinding.instance.addPostFrameCallback((_) {
        scrollController.jumpTo(scrollController.position.maxScrollExtent);
      });
      return null;
    }, const []);
```
`body`の部分の実装になります。こちらで`Stack`部分のスクロール調整を行います。今回は記述していませんが、場合によっては`Scaffold`直下に`resizeToAvoidBottomInset: false`を設定して下さい。
```dart
body: Stack(children: [
        // まずこのSingleChildScrollViewでラップする必要がある
        SingleChildScrollView(
            // controllerでスクロールされる位置を制御
            controller: scrollController,
            // 入力に対してスクロールが境界を超えないように制御
            physics: ClampingScrollPhysics(),
            // 読み取り方向にスクロールさせたいのでreverseをtrueに
            reverse: true,
            // Paddingでラップしてbottom部分の余白を取ります
            child: Padding(
              padding: EdgeInsets.only(bottom: bottomSpace),
```
仕上がりはこんな感じになります↓
![スクリーンショット 2022-10-05 15.24.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/60c83e6a-cc3b-f1cb-8756-60cafd27332e.png)
<details><summary>全体のコードはこちらをタップして下さい。</summary><div>

```dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class TextView extends HookConsumerWidget {
  const TextView({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final _controller = useTextEditingController();
    final text = useState('');

    // キーボードの高さを取得してbottomSpaceにいれる
    final bottomSpace = MediaQuery.of(context).viewInsets.bottom;
    // SingleChildScrollViewを管理
    final scrollController = ScrollController();
    useEffect(() {
      // ビルド直後にscrollControllerの位置を調整
      WidgetsBinding.instance.addPostFrameCallback((_) {
        scrollController.jumpTo(scrollController.position.maxScrollExtent);
      });
      return null;
    }, const []);

    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Stack(children: [
        // まずこのSingleChildScrollViewでラップする必要がある
        SingleChildScrollView(
            // controllerでスクロールされる位置を制御
            controller: scrollController,
            // 入力に対してスクロールが境界を超えないように制御
            physics: ClampingScrollPhysics(),
            // 読み取り方向にスクロールさせたいのでreverseをtrueに
            reverse: true,
            // Paddingでラップしてbottom部分の余白を取ります
            child: Padding(
              padding: EdgeInsets.only(bottom: bottomSpace),
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Container(
                        padding: const EdgeInsets.all(50.0),
                        child: Column(
                          children: <Widget>[
                            Text(
                              '${text.value}',
                              style: TextStyle(
                                  color: Colors.blueAccent,
                                  fontSize: 30.0,
                                  fontWeight: FontWeight.w500),
                            ),
                            new TextField(
                                controller: _controller,
                                enabled: true,
                                maxLength: 10,
                                maxLengthEnforcement:
                                    MaxLengthEnforcement.enforced,
                                style: TextStyle(color: Colors.red),
                                obscureText: false,
                                maxLines: 1,
                                onChanged: (String e) {
                                  text.value = e;
                                }),
                          ],
                        )),
                  ],
                ),
              ),
            )),
        Align(
            alignment: Alignment.bottomCenter,
            child: Container(
                height: 47,
                width: 297,
                margin: EdgeInsets.only(bottom: 20),
                decoration: BoxDecoration(
                    color: Colors.white,
                    border: Border.all(color: Colors.white),
                    borderRadius: BorderRadius.circular(10),
                    boxShadow: [
                      BoxShadow(color: Color(0x19000000), blurRadius: 14)
                    ]),
                child:
                    Row(mainAxisAlignment: MainAxisAlignment.center, children: [
                  GestureDetector(
                      onTap: () {
                        Navigator.pop(context);
                      },
                      child: Text('戻る',
                          style: TextStyle(fontSize: 18, color: Colors.black))),
                ])))
      ]),
    );
  }
}
```
</div></details>