Skip to content

DNET_Flutter4thStep

nishi_74322014 edited this page Sep 11, 2026 · 1 revision

Flutterの4thステップ

概要

Flutter の step by step(其の四)。

手順1:業務ぃーな、CRUDを実装してみる。

入力フォームの作成

  • 公式のサンプルに問題があるらしい。
  • 取り敢えず、基本のTextFormFieldを使ってみる。

前編

  • ファースト・ステップ
    以下のような感じ。

    // main.dart
    Form(
      child: Column(
        children: [
          TextFormField(
            decoration: InputDecoration(labelText: 'id'),
          ),
          TextFormField(
            decoration: InputDecoration(labelText: 'password'),
            obscureText: true, // 追加
          ),
        ],
      ),
    )
  • セカンド・ステップ
    以降、技術は熱いうちに打てが参考になる。

    • doneボタンが押された時の処理を記述
    • doneからnextに変更しフォーカス移動
    • 初期値設定と現状値の保存
    • インライン・バリデーション処理の実装
  • ポイント

    • その1: 意味もなくsave()するな。
      単に、子要素のonSave()を呼ぶ処理なので。

    • その2: 意味もなくステートを持つな。
      FormにGlobalKey<FormState>張って、
      GlobalKey<FormState>.currentState?.save()で上記のonSave()が動作。

    • その3: やたらめったらFormを書き換えるな。
      要するに、setStateを書かなくてもイイというコトらしい。

    • その4: 初期値を入れるのにTextEditingControllerを使うな。
      TextFormField.initialValueを使用する。

    • その5: AutofillHintsちゃんと書こう。
      HTML.Inputタグで言うところのautocomplete属性。

後編

  • サード・ステップ

    • 現状値の保存に対して、現状値の設定は?
      FormFieldStateにGlobalKey<FormFieldState>張って、
      GlobalKey<FormFieldState>.currentState?.didChange(this._XXXX)。

    • ドロップダウンリスト
      DropdownButton(Flutterのファースト・ステップの該当節を参照)を使用する。

    • バリデーション処理が長い。

一覧表示の作成

WebAPIでデータを取得する。

JSONをdecodeする。

decodeするdart:convertライブラリのサンプルが複数ある。

  • JSON.decodeは古いライブラリ。

  • 今は、jsonDecodeのライブラリを使用する。

  • 以下の何れかの方に変換される模様。

    • Map<String, dynamic>
    • List<dynamic>

    DBの一覧ならList<dynamic>になる。

DataTableを使用した一覧

  • 業務系では、DataTableのWidgetが使えそう。

  • Bindingは、DataTableの、

    • columns: で、列定義を行い、
    • rows: で、DataRow / DataCellのlistを返す。

ListViewを使用した一覧

  • ListView.builderのitemBuilderでcardデザインを返す。
  • cardデザインはプッシュ通知(Flutterのサード・ステップの該当節を参照)のサンプル中に含まれる。

, etc.

未記載(元 Wiki も見出しのみ)。

参考(手順1)

Qiita(手順1)

手順2:気になっている所を修正する。

画面遷移処理

  • 画面内の遷移とDrawerの遷移(Flutterのファースト・ステップの該当節を参照)がゴッチャになる。

  • 調べていくと、最初に表示された画面は、
    ルートなので、ソレ以上、POPできないらしい。

  • 以下の修正を加えると、ソレっぽくなる。

画面内の遷移は、スタックにプッシュする。

(push については Flutterのファースト・ステップ の該当節を参照)

故に、戻る処理は、

  • 基本的に、戻るボタンで前画面に戻る。
  • 処理次第でpopを明示的に実装する。

Drawerの遷移は、一度スタックを空にする。

(Drawer については Flutterのファースト・ステップ の該当節を参照)

以下のように実装する。

  • ルートへの遷移
    ルートまでpopする。

    onTap: () {
      while(Navigator.of(context).canPop()){
        Navigator.of(context).pop();
      }
    },
  • ルート以外への遷移
    ルートまでpopした後、1つダケpushする。

    onTap: () {
      while(Navigator.of(context).canPop()){
        Navigator.of(context).pop();
      }
      Navigator.of(context).pushNamed("/appauth");
    },

Widgetの部品化

  • 全体構成の見直し の common(いずれも Flutterのサード・ステップ の該当節を参照)に入れる。

  • StatelessWidgetでラップする方法と、
    Widgetをextendsする方法がある模様。

    • 前者は、簡単な特化型のカスタマイズ
    • 後者は、高難易度の汎化型のカスタマイズ
  • C#的に言うと、

    • StatelessWidgetでラップする方法
      ユーザ・コントロール的にラップするか?
    • Widgetをextendsする方法
      カスタム・コントロール化するか?

    みたいな。

  • Windows Formsのようなオナー・ドローは不要。
    WPFのように子要素で実装可能(Widget buildメソッドで返す)。

Drawer

  • StatelessWidgetでラップする方法
    • 定義して

      import 'package:flutter/material.dart';
      
      class MyDrawer extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return Drawer(
    • 使用する。

      return Scaffold(
        ...,
        drawer: MyDrawer(),
      );

Button

  • StatelessWidgetでラップする方法
    • 定義して

      import 'package:flutter/material.dart';
      
      class MyElevatedButton extends StatelessWidget {
      
        final String _caption;
        final VoidCallback _onPressed;
      
        const MyElevatedButton(
            this._caption, this._onPressed,
            {Key? key}) : super(key: key);
      
        @override
        Widget build(BuildContext context) {
          return ElevatedButton(
            child: Text(this._caption),
            ...,
            ),
            onPressed: this._onPressed,
          );
        }
      }
    • 使用する。

      MyElevatedButton('EnglishWords Button', this._englishWords),

FormField

  • 対象のWidgetをextends する方法

    • 定義して

      class CounterFormField extends FormField<int> {
      
        CounterFormField({
          FormFieldSetter<int> onSaved,
          FormFieldValidator<int> validator,
          int initialValue = 0,
          bool autovalidate = false
        }) : super(
          onSaved: onSaved,
          validator: validator,
          initialValue: initialValue,
          autovalidate: autovalidate,
          builder: (FormFieldState<int> state) {
            return Row(
             この中で、state.valueとかstate.didChangeが使える。
            );
          }
        );
      }
    • 使用する。

      CounterFormField(
        autovalidate: false,
        validator: (value) {
          ...
        },
        onSaved: (value) => this._value = value,
      )

, etc.(Widgetの部品化)

未記載(元 Wiki も見出しのみ)。

その他の共通化

全体構成の見直し の 各フォルダ(Flutterのサード・ステップの該当節を参照)に入れる。

変数/定数クラス

→ configs(Flutterのサード・ステップの該当節を参照)

関数クラス

→ helpers(Flutterのサード・ステップの該当節を参照)

サービス・クラス

→ services(Flutterのサード・ステップの該当節を参照)

参考(手順2)

参考

Flutterの参考

  • Flutterの参考(Flutterの該当節を参照)

Flutterの5thステップ

移行メモ

  • 元 Wiki では見出しそのものが他ページ・同ページ内へのリンクになっていた箇所 (「WebAPIでデータを取得する。」「画面内の遷移は、スタックにプッシュする。」 「Drawerの遷移は、一度スタックを空にする。」「Flutterの参考」 「Flutterの5thステップ」)は、GitHub Wiki では見出しからアンカが 生成されるため、見出しをプレーン・テキストとし、リンクは直下の本文に置いた。
  • 同名の見出し(「参考」「Qiita」「, etc.」)が複数あり GitHub Wiki でアンカが衝突するため、括弧で文脈を補って一意にした。
  • GlobalKey<FormState> などの山括弧は、そのままでは HTML タグとして 解釈されるため、本文中では実体参照(&lt; / &gt;)で記述した。
  • PukiWiki のページ内アンカ(#xxxxxxxx)は GitHub Wiki では再現できないため、 同一ページ内のアンカは見出しから生成されるアンカに張り替え、 他ページのアンカを指すリンクは「〜(ページ名 の該当節を参照)」の形に置き換えた。
  • マイクロソフト系技術情報 Wiki(techinfoofmicrosofttech.osscons.jp)への URL リンクは、移行済みの .NETコントロールのカスタマイズ方法 に張り替えた。
  • 元 Wiki の行頭空白によるプレフォーマット・ブロックは、 フェンス付きコードブロックにした。
  • リンク先が未移行のページは、移行先のファイル名を `DNET_○○.md` の形で示し TODO.md に登録した。

Tags: 移行, Flutter, CRUD, TextFormField, バリデーション, DataTable, ListView, Navigator, Widget部品化, FormField

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally