【Dart/Flutter開発】表示制御と検索機能の実装、実際の(自作)アプリと考え方を共に...【スマホアプリ】
こんにちは、たちつてとです。
ゆるい収支管理アプリのベースができたので、
そこまでにどういう記述が必要だったかをまとめました。
ちなみに見た目に関しては、簡単にですが
【Flutter/Dart開発】見た目を整えるための基礎知識をまとめた【スマホアプリ】
でまとめました。
一覧型の画面と登録型の画面を作ったのですが、まず一覧型の画面から。
画像の通り、日付とお金(出費)が対応した一覧画面になります。
画像の通り、機能は
- ボタン押下で、表示/非表示になるエリアがある。
- ボタン押下で、表示される日付のデータが変わる(検索)
になります。※データは、すでに登録してあるものです。
ちなみに、
画像上部の「2021年」や「10月」などをタップすると、
(ドロップダウンという要素)選択肢が表示されます。
本記事では、数字や日付などいわゆる「完全一致」の
絞り込みをしています。
以下記事では、検索バー的なものも実装してみました。
【Dart/Flutter開発】検索エンジンでありがちな、単語/言葉の検索機能(検索バー)を実装する、話
この記事では、「部分一致」、つまり
キーワードを「含む」検索になります。
【余談】
月ドロップダウンは、
タップすると1〜12月までの選択肢が表示されます。
あまりにも冗長だったので、
画面下部のボタンも実装しました。
順番に見ていきましょう!
ボタン押下時の表示制御
ここで必要なことは、二つです。
- ボタンテキストの「+」/「ー」切り替え←発想の話
- 該当エリアの表示制御←文法の話
まあ、知ってしまえばいずれも簡単な話なのです。
ボタンテキストの「+」/「ー」切り替え
日本語で書くと、
「ボタン押下時に該当ボタンのテキストを変える」です。
まあほぼそのまま...
→ボタンのテキストを変数にしちゃえって感じです。
はい、ソースです。
といっても該当部分だけ取ってきているのでチグハグですが...
細かい文法は割愛しまして、
作戦をお伝えできればと思います。
ListView.builder(
// リストを生成
itemBuilder: (context, index) {
Container(
child: SizedBox(
height: 50,
child: FloatingActionButton(
heroTag: "flt_open" + index.toString(),//heroTagは各ボタンでユニーク
onPressed: () {// ボタン押下時の処理
setState(() {// 一番大事な処理
if (isOpen == true) {
_openDetail[index] = false;
_buttonText[index] = '+';
} else {
_openDetail[index] = true;
_buttonText[index] = 'ー';
}
});
},
child: Text(_buttonText[index]),
)),
)
一覧を作るために、ListView.builderを使用しています。
細かい文法は割愛。
FloatingActionButtonというやつが、
「+」/「ー」ボタンの本体になります。
- 「+」/「ー」表示用のList<String> _buttonText
- 自身の開閉状態を記録するためのList<bool>_openDetail(後述)
をクラスのフィールドとして用意しています。
で、具体的な処理は、
OnPressの中にsetStateする
あとは機械的にbulidメソッドが呼び出され、
画面が変わります。
お次。
表示制御
こちらは、知識の話になります。
こちら
Visibility(
visible: isOpen,
child:
表示/非表示を切り替えたい要素を
Visibilityというのでラップし
(child以下に書き)ましょう。
isOpen = _openDetail[index]であり、
先述の通り
- 自身の開閉状態を記録するためのList<bool>_openDetail
です。お分かりかと思いますが、
visible:true(=表示)、false(非表示)になります。
上述のOnPressでtrue/falseを切り替えることで、
「ボタン押下時に該当ボタンのテキストを変える」
を実現しています。
検索機能
こちらは、人によって書き方がまちまちになるかもしれません。
データをMap型の感じで保存するので、
keyと検索条件を比較して
(一覧をつくるための)
List型にaddするという方針です。
(僕は、「Hive」という
スマホのストレージに
データを保存する方針を取っています。)
ソース自体はあんまり参考にならない思いますが...
void loadData() async {
Hive.openBox<Mesai>(_mesai).then((value) {// 人によってまちまち
Box<Mesai> mesBox = value;
// List型をリセット
_dayMesai.clear();
_openDetail.clear();
_buttonText.clear();
// List型を作り直し
for (Mesai mesai in mesBox.values) {// 変数など人によってまちまち
String date = mesai.dateNo.split('_')[0];//keyをいい感じに取り出す
if (date.split('/')[0] == _year &&
date.split('/')[1] == _month.padLeft(2, "0")) { // 検索条件を反映
_dayMesai.add(mesai);
_openDetail.add(false);
_buttonText.add('+');
}
}
//以下も人によってまちまち
Container clm = getContainer();
asyncWidget = clm;
});
}
このloadDatamなるメソッドを、
ドロップダウンやボタンの変更/tapイベントに仕込んでいます。
大事なこと/考え・処理をまとめると、
- ボタン等のtapイベントで
- 検索条件用のフィールドに値を(setStateで)セット(_year=2021とか_month=6とか)
- loadData呼び出し(ここから↑ソース)
- List型をリセット
- forで検索条件を反映させつつ作り直し
しています。
以下は完全に僕専用の動きで、具体的には、
- date = 2021/08/01_1(=日付_連番)(=mapのkeyです)みたいな形式
- date.split('_')で日付と連番を分ける
- ↑配列[0]が日付に対応→その日付をsplit('/')でさらに年[0]と月[1]を取り出す
- 一方、今選択されている値(=2021年とか9月)と比較
- 該当するkeyの要素だけが、Listにaddされる
非効率かもしれませんが、完全に趣味の世界なので許して...?
ちなみに、
「まへ」とか「いま」とかいう(ふざけた)ボタンは、
1ヶ月移動するボタンです。
これも特別なことはなく、
「まへ」/「つぎ」ボタン:選択されている月プラマイ1
「いま」:DateTime.now()から年と月を取り出す
を検索条件用の(_yearとか_monthとか)変数に入れてるだけです。
まとめ
はい、まとめです。
要は、
- Visibilityで該当エリアをラップ
- ボタンテキストを変数化(=フィールド化)して、
- ボタンやドロップダウンのイベント時に(setState等で)セット
こんな感じになります(あっさりしすぎ?)。
javaの知識のみならず、
オブジェクト指向の知識を入れたい方は↓左の書籍。
結構かぶっているところがあります。
自分もjavaのにわか知識に助けられました。
Dartを勉強したいぜ!な方は右の書籍。
購入から数週間後、右の本の後ろに
Dartの文法が載ってて唖然としました。
「初めから知ってれば、
ここまで苦労しなかったのでは...?」
|
|