LoginSignup
3
2

More than 3 years have passed since last update.

Flutter で汎用的な入力ページを考える

Last updated at Posted at 2019-12-25

今年は、Flutterを使用し、いくつかのアプリをリリースすることができました。

その中で、会員登録などの入力ページでチームのスタンダードになってきているなぁという部分がありましたので紹介したいと思います。

入力ページのイメージ

会員登録ページを例にあげると、現在担当しているアプリは下記のような、一度に情報を登録せず、ページ遷移させる事が多いです。

ページの遷移.png

first.png

main.dart
body: Column(
        children: <Widget>[
          Padding(
            padding: EdgeInsets.symmetric(vertical: 30),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text('XXXXXを入力してください。'),
                Text('XXXXXはあとからマイページにて変更することも可能です。'),
              ],
            ),
          ),
          TextField(),
          Expanded(child: Container()),
          Padding(
            padding: EdgeInsets.only(bottom: 50),
            child: RaisedButton(child: Text('次へ進む')),
          ),
      ])

縦に長い場合エラー

しかし文言が増えたときなど、縦幅が長くなった場合、bottom overflowedエラーが出てしまいます。

スクリーンショット 2019-12-25 12.35.37.png

対策として、画面をタップするとキーボードが閉じる処理を入れます。

main.dart
body: GestureDetector(
          onTap: () => FocusScope.of(context).unfocus(),
          child: Column(children: <Widget>[
        Padding(
          padding: EdgeInsets.symmetric(vertical: 30),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Text('XXXXXを入力してください。'),
              Container(
                height: 500,
                color: Colors.green,
              ),
            ],
          ),
        ),
        TextField(),
        Expanded(child: Container()),
        Padding(
          padding: EdgeInsets.only(bottom: 50),
          child: RaisedButton(child: Text('次へ進む')),
        )
      ])),
      resizeToAvoidBottomInset: false, //追加部分

全体を GestureDetector で囲み、 onTap でフォーカスを外す処理を入れ、キーボードを隠すようにします。
また、 resizeToAvoidBottomInset でキーホードの表示/非表示でボタンの位置が変わらないようにします。

もっと長い場合は

ページが長い場合はスクロール処理を入れますが、スクロールを行なった際にもキーボードを閉じる処理を入れたいです。

main.dart

body: NotificationListener(
      child: SingleChildScrollView(
          dragStartBehavior: DragStartBehavior.down,
          child: GestureDetector(
              onTap: () => FocusScope.of(context).unfocus(),
              child: Column(children: <Widget>[
                Padding(
                  padding: EdgeInsets.symmetric(vertical: 30),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text('XXXXXを入力してください。'),
                      Text('XXXXXはあとからマイページにて変更することも可能です。'),
                      Container(
                        height: 500,
                        color: Colors.green,
                      ),
                    ],
                  ),
                ),
                TextField(),
                Padding(
                  padding: EdgeInsets.only(top: 50, bottom: 50),
                  child: RaisedButton(child: Text('次へ進む')),
                )
              ]))),
      onNotification: (ScrollNotification scrollInfo) {
        FocusScope.of(context).unfocus();
      }),
  resizeToAvoidBottomInset: false,

SingleChildScrollView で全体を囲み、 さらに NotificationListener で囲みます。
Expanded はスクロールの中に入れられないので外します。
onNotification でスクロールが発生した際にフォーカスを外す処理を入れて出来上がりです。

サンプルのプログラムをgithubにあげました

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2