【Flutter/Dart開発】初!アニメーションを導入/表示制御をちょっとおしゃれにしてみた話【スマホアプリ】
こんにちは、たちつてとです。
表題通り、アニメーションを導入してみました。
やりたいこと
みていただきたいのは、上画像の
左から1,2番目のスマホ画面。
出費管理アプリを作って
独りで使っているんですが。
完成物。
モチベーション
毎月、固定費を入力をしなければならない
ことに気づき、いやだる。となったので
実装しました。
固定費の設定画面になります。
まあ、細かいことはよくて、
入力画面を新しく作るのも、いやだる。と
思ったからではないんですが、
めんどくさいものはめんどくさいので
一覧編集画面にて一括登録形式で
固定費を設定しようと思いました。
そこでネックなのは一覧画面なだけに
一行にたくさんのスペースを使うのもな...
ということでして。
ならタップで表示切り替えすれば
コンパクトになるんじゃね?
と思いました。これだけなら
Widget的にはVisiblityというのがありますので
タップイベントでVisibleをtrue/falseで
切り替えれば、はいOK。となります。
でもそれだけだとつまんなくね。
と思ったので、アニメーションを導入しました。
なんという向上心と啓蒙!
コード
Container getContainer() {
return Container(
child: ListView.builder(
// リストを生成
itemBuilder: (context, index) {
final cost = _costList[index];// 独自変数
return
Card(
child: ListTile(
title: Column(children: <Widget>[
Container(
height: 60,
child: AnimatedSwitcher(// 中核
duration: const Duration(seconds: 1),// 時間設定
// 独自メソッド
child: getRenderWigit(_widMode[index], index, _costList[index]),
transitionBuilder:
(Widget child, Animation<double> animation) {
final offsetAnimation = Tween<Offset>(
begin: Offset(0.0, 1.0), end: Offset(0.0, 0.0))
.animate(animation);// 位置設定等
return ClipRect(
child: SlideTransition(
position: offsetAnimation,
child: child,
),// スライドの感じに
);
},
)),
]),
onTap: () {// tapイベント
setState(() {
if (_widMode[index] == "") {// モード切り替え用の変数にしこむ
_widMode[index] = "1";
} else {
_widMode[index] = "";
}
});
},
),
);
},
itemCount: _costList.length, // 制限
),
);
}
というメソッド(戻り値:Container)をScaffoldのbodyにぶち込みます。
変数/処理で重要なこと
オリジナルな変数は_costList, _widModeになります。
ここでは、一覧画面ということでいずれの変数も
List型になります。それぞれ
List<RegularCost>, List<String>型
となります。
前者は独自のクラスなので参考にならない思いますが...
大事なのは、
前者が表示したいList変数で
後者が一行ごとに表示制御を切り替えるための変数
となります。
そして、上記ソースの通り
OnTap、タップイベントに
後者のモード制御用の変数の値を切り替えています。
値が
- ""、空ならデフォルトモード(以下ソースでは詳細略)
- "1" なら日付入力用モード(以下ソースでは詳細略)
となります。
アニメで重要なこと
AnimetedSwitcher
というのがアニメーションにおいて
最も重要になります。
基本的にはコメントした通りになっています。
これによって、上述の表示モードの切り替えが
(滑らかに動く)アニメーションになります。
Offset
ちょっと調べた感じ、
近いのは「補正値」という意味ですかね?
僕の経験としては、仕事とかでライブラリ使ってると
システムの見た目をちょっと修正したい
→「ある基準値からのずれ」を設定するために
なになにOffsetという関数を使ったりします。
ここでは、本来ある位置がoffset(0.0, 0.0)で、
ここを始点にアニメにしたいぜ(start)
→offset(0.0, -1.0)
としてます。
offsetの引数はそれぞれ
横方向、縦方向です。
ですので、横方向にアニメにしたいときは
例えば、
- startをoffset(-1.0, 0.0)
- endをoffset(0.0, 0.0)
とする。最後には本来の位置にいて欲しいので、
endは0,0です。
もちろん、斜めにしたければ
(-1.0, -1.0)や(1.0, 0.5)
とかもあり。
表示切り替え用のメソッド
最後に、以下のコード。
getRenderWigit(widMode, index, cost) {
if (widMode == "") {// 表示モード デフォ
return Container(
key: Key("Text" + index.toString()),
height: 60,
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Card(
child: Container(
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
key: Key('Text' + index.toString()),// Key指定必須
initialValue: 'Text',
style: TextStyle(fontSize: 16),
textAlign: TextAlign.left,
))),
Card(
color: Color.fromRGBO(255, 255, 255, 1.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.4
)
),
]),
);
} else {// 表示モード1
return Container(
alignment: Alignment.center,
key: Key("Date" + index.toString()),// Key指定必須
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
],
));
}
}
こんな感じのメソッドで
ifによってモードの切り替えをしています。
引数のwidModeがsetStateするたびに変化
→戻り値のContainerの内容も変わる
という感じで、表示切り替えのアニメーションができます。
まとめ
- AnimetedSwitcherを利用
- タップイベントに表示制御変数の値が変わるよう仕込む
- 表示制御用の変数値によって表示が変わるようにメソッドを用意
説明は以上となります。
お疲れ様でした。
|
|