綴Photo で、写真を記録したときに出るメッセージを作り直した。発端は大層なものじゃなくて、作っている最中に保存を試していて「保存しました」のトーストがなんか見にくくて微妙だなと思ったこと。最終的に「3目の記憶に、パタンと綴じました」というテキストに落ち着いた。
発端:「保存しました」が、自分で使ってて見にくかった
最初のバージョンは、普通に「保存しました」というトーストを出していた。機能としては何も問題ない。写真を保存したことは伝わる。
でも、作りながら何度も保存を試していると、この表示が地味で見にくいのが気になってきた。一瞬出て消える灰色の通知。味気ないし、目にも留まらない。
「もっといい見せ方ないかな」というところから始まった。最初に思いついたのは「画像を出す」案だった。イラストっぽいものをパッと出せば、もっと印象に残るんじゃないかと。
ただ、保存のたびに毎回画像を出すのは描画的に重いですし、画像自体を作り込むのも大変です。試しに方向を変えて、「言葉」と「ちょっとしたアニメ」だけでどこまで印象を変えられるかをやってみることにした。結果、画像は使わずにこっちで十分だった。
たどり着いたメッセージと、その中身
落ち着いたメッセージが「3目の記憶に、パタンと綴じました」。要素は2つ。
①「○目の記憶」 ─ 件数を入れる
// ローカル DB(Drift)に登録された写真の総件数を取得
final memoryCount = await db.photoDao.countPhotos();
final message = '$memoryCount目の記憶に、パタンと綴じました';件数が毎回変わるので、単なる通知じゃなくて「積み上がってる」感じが出た。
②「パタンと綴じました」 ─ 動詞と擬音語
「保存」ではなく「綴じる」。「パタン」という擬音語で、アナログのアルバムを閉じる感触をイメージしてもらいたかった。
見せ方:アニメーションとタイマー
メッセージのアニメーションは AnimatedOpacity と AnimatedScale の組み合わせ。フワッと出てフワッと消えるだけだが、これだけで「ただの通知」感がかなり減ります。
AnimatedOpacity(
opacity: _visible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 300),
child: AnimatedScale(
scale: _visible ? 1.0 : 0.85,
duration: const Duration(milliseconds: 300),
child: FeedbackToast(message: message),
),
),_timer = Timer(const Duration(milliseconds: 1400), () {
if (mounted) setState(() => _visible = false);
});1.4秒は「読める速さ」と「邪魔にならない速さ」のバランス。短すぎると読めない、長すぎると邪魔。実機で確認しながら、この数字に合わせた。
タイマーのライフサイクル管理は mixin に切り出して、dispose 忘れによるメモリリークを防いでいます。
作ってみてどうだったか
実機で動かすと、保存のたびに件数が増えて、灰色の「保存しました」よりはだいぶ見やすくなった。見にくさという最初の不満は解消したし、「保存」より綴Photo らしい手触りになった。
やってみて分かったのは、コピーはほぼ技術コストゼロで見た目の印象を変えられるということ。画像を作り込まなくても、言葉と軽いアニメだけでここまで変わるのは想定外だった。
まとめ
- 出発点は「保存表示が見にくい・微妙」という、自分で使ってての不満
- 最初は画像も考えたが、言葉+軽いアニメで十分だった
- 「パタンと綴じました」は AI 提案をそのまま採用。良いと思ったら入れてみる
- 件数を入れると「積み上がってる」感が出る
言葉まわりは個人開発ではつい後回しになりがちで、「まず動けばいい」で「保存しました」のまま放置しがち。でも保存のたびに必ず出る部分だから、見にくいと地味に気になった。直してよかった、くらいの話。
この記事は2026年4月時点の実装内容で書いています。コピー文や数値(表示時間1.4秒など)は調整中なので、現在の実装と差分があるかもしれない。