BETA

Flutter で Hello World⑧

投稿日:2020-09-20
最終更新:2020-09-20

ListTileにポップアップメニューを実装する

アプリをリリースして使用しているうちに、いくつかの機能的な不足が目立つようになってきたので対応する。
まず、必要と痛感したのがListTileとして表示されているデータの削除機能だ。

支払の履歴は、右下のフローティングボタンをタップすると増えていく。アプリ起動中にうっかり右隅を触ってしまうと意図せず支払履歴を増やしてしまうことになるのだ。

そこで、各明細にポップアップメニューを追加して、削除できるようにしてみる。

enum Menu { mod, del }  

class PopupMenu extends StatelessWidget {  
  PopupMenu({Key key, this.itemid, this.itemfee}) : super(key: key);  
  final int itemid;  
  final int itemfee;  

  Widget build(BuildContext context) {  
    return PopupMenuButton(  
        onSelected: popupMenuSelected,  
        itemBuilder: (BuildContext context) =>  
          <PopupMenuEntry<Menu>>[  
            const PopupMenuItem(  
              child: const ListTile(  
                leading: Icon(Icons.edit),  
                title:Text('編集')  
              ),  
              value: Menu.mod,  
            ),  
            const PopupMenuItem(  
              child: const ListTile(  
                leading:Icon(Icons.delete),  
                title:Text('削除')  
              ),  
              value: Menu.del,  
            ),  
          ],  
    );  
  }  

ざっくりと作ったメニューのレイアウトは、今回実装する削除と、金額を修正できる編集の2項目を用意した。なんか余白が多くてやぼったいが、今はこのまま放置する。

  void popupMenuSelected(Menu selectedMenu) async {  

    switch(selectedMenu) {  
      case Menu.del:  
        await refund(itemid, itemfee);  
        break;  
      default:  
        break;  
    }  
  }  

PopupMenuのどの項目をタップしてもこのPopupMenuSelectedがコールされる。選択されたメニューのvalue値で実施する処理を切り分けられるようにしている。実際の削除処理はrefundの中で実装しているが、渡されたitemidをキー条件にしてテーブルからレコードを削除している。

ListTileの項目値を編集する

もう一つ欲しかった機能は、一度はランダムで決定した支払額を修正できる機能だ。一度はランダムで支払いを済ませたが、実際の支払額と差分が生じてしまう場合などに使用する想定だ。ポップアップメニューが実装できているので、後は編集のための処理を組み込むだけでよい。

  void popupMenuSelected(Menu selectedMenu) async {  

    switch(selectedMenu) {  
      case Menu.del:  
        await refund(itemid, itemfee);  
        break;  
      case Menu.mod:  
        await correct(itemid, itemfee);  
        break;  
      default:  
        break;  
    }  
  }  

まずはポップアップメニューのタップイベントにコールするメソッドを記述する。

  1. タップされたポップアップが持つidと支払額を取得する
  2. ダイアログを表示し、もともとの支払額を初期値として表示する
  3. ダイアログの戻り値を修正された支払額とする
  4. もともとの支払額と修正された支払額の差額を所持金に加算する
  5. idをキー条件としてテーブルの金額を更新する

ダイアログの初期表示

入金ボタンをタップした際の処理としてダイアログ画面を作成してあるが、これは初期値としては何も表示されない。そこで初期値を表示できるように修正する。

ダイアログの金額はTextFieldで実装しているが、これに初期値を設定する場合、TextEditingControllerを使用する。

class DepositDialog extends StatefulWidget {  
  DepositDialog({Key key, this.initial}) : super(key: key);  
  final int initial;  

  @override  
  _DepositDialogState createState() => _DepositDialogState();  
}  
class _DepositDialogState extends State<DepositDialog> {  
  TextEditingController _appCtrl;  

  @override  
  void initState() {  
    super.initState();  
    if (widget.initial == null) {  
      _appCtrl = TextEditingController();  
    } else {  
      _appCtrl = TextEditingController(text: widget.initial.toString());  
    }  
  }  

  @override  
  Widget build(BuildContext context) {  
    final List<Widget> actions = [  
      ...  
    ];  
    final AlertDialog dialog = AlertDialog(  
      title: Text('入金額'),  
      content: TextField(  
        controller: _appCtrl,  
        decoration: InputDecoration(hintText: '半角数字で入力してください'),  
        autofocus: true,  
        keyboardType: TextInputType.number,  
        inputFormatters: <TextInputFormatter> [  
          WhitelistingTextInputFormatter.digitsOnly,  
        ],  
      ),  
      actions: actions,  
    );  

    return dialog;  
  }  
}  

すでにダイアログのUIの中でTextEditingControllerは使用しているので、ダイアログの表示時点で引数に初期値が入っていた場合は初期値を、なければ従来通り何も表示しないように切り分ける処理をinitState内に実装した。

これで修正と削除ができるようになり、実用に耐えうるレベルになっただろうか。しばらくは自分で使ってみて問題点を出すしかない。だってダウンロード数1とかいう、クソアプリですからね。

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

そろそろ業界からオプトアウトされそうな枯れ老人の足掻きブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう