つてとのブログ

【Flutter/Dart開発】初!アニメーションを導入/表示制御をちょっとおしゃれにしてみた話【スマホアプリ】

こんにちは、たちつてとです。

表題通り、アニメーションを導入してみました。

 

やりたいこと

f:id:tachitutetoNosuke:20211105193833p:plain

みていただきたいのは、上画像の

左から1,2番目のスマホ画面。

 

出費管理アプリを作って

独りで使っているんですが。

完成物。

f:id:tachitutetoNosuke:20211106183103g:plain

 

モチベーション

毎月、固定費を入力をしなければならない

ことに気づき、いやだる。となったので

実装しました。

固定費の設定画面になります。

 

まあ、細かいことはよくて、

入力画面を新しく作るのも、いやだる。と

思ったからではないんですが、

めんどくさいものはめんどくさいので

一覧編集画面にて一括登録形式で

固定費を設定しようと思いました。

 

そこでネックなのは一覧画面なだけに

一行にたくさんのスペースを使うのもな...

ということでして。

 

ならタップで表示切り替えすれば

コンパクトになるんじゃね?

 

と思いました。これだけなら

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を利用
  • タップイベントに表示制御変数の値が変わるよう仕込む
  • 表示制御用の変数値によって表示が変わるようにメソッドを用意

説明は以上となります。

お疲れ様でした。

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

Android/iOSクロス開発フレームワークFlutter入門 [ 掌田津耶乃 ]
価格:3300円(税込、送料無料) (2021/10/25時点)

楽天で購入
[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

Flutter モバイルアプリ開発バイブル [ 南里勇気 ]
価格:3509円(税込、送料無料) (2021/9/20時点)

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

Javaのオブジェクト指向がゼッタイにわかる本[第2版] [ 立山秀利 ]
価格:2530円(税込、送料無料) (2021/9/26時点)

エンジニア発オンラインスクール【RUNTEQ】