綴Photo の勉強ノートに戻る
プロダクト設計2026.04.04

昔の写真に「今日の気持ち」を書き足せるアプリを作っている。重ねる UX とその実装

FlutterUX設計プロダクト設計綴Photo

綴Photo には、 1枚の写真に対して、複数の言葉を後から重ねて書ける機能があります。 3年前の旅行の写真を今見たときの気持ちも、ちゃんと記録に残せます。 このコンセプトと、それを支える UX/実装の方針を残しておきたい。


なぜ「重ねる」を作ろうと思ったか

最初は素直に「写真 1 枚 = 言葉 1 つ」で考えていた。 SNS と同じ感覚だ。投稿は基本 1 回、その時の気持ちが添えられます。

でも、大切な写真ってそれだと足りない、と途中で気づいた。

  • 撮った当日に書く言葉
  • 1ヶ月後に見返して書ける言葉
  • 3年後にまったく違う視点で書ける言葉

これはどれも「同じ写真への気持ち」だけど、まったく違う情報だ。 1つ目を上書きするのも、別の写真として保存するのも、 俺がやりたいことと違っていた。

「同じ写真に、層を重ねていく」。 このメタファーが頭の中で固まったとき、機能の形が見えた。


詰まったところ:「重なってる」ってどう見せるか

データの形は割とすぐ決まった(写真 1:N 言葉)。 詰まったのは UI/UX の方だった。

「同じ写真に複数の言葉が紐付いている」状態を、ユーザーにどう見せるか。

最初に試した案たち。

  • A: 言葉をリストで縦に並べる → SNS の投稿一覧みたいで、味気ない。「重ねた」感が出ない
  • B: 写真の上にテキストオーバーレイで重ねる → 写真が見えなくなる。読みにくい
  • C: 写真の下に時系列でカード状に並べる → A と似ているけど、見た目をノートのページっぽくすると意味が変わる

最終的には C をベースにした。 ただし、ただ並べるんじゃなくて、

  • 一番新しい言葉が一番上(最新の気持ちが先に目に入る)
  • 古い言葉ほど下に流れていく
  • 各エントリには「綴った日」を付ける

という形にした。

「重ねる」の方向は、現実のノートだと上に書き足していくものです。 だからアプリ上でも、新しいものが上にスタックします。 このメタファーが揃うと、ユーザーが説明されなくても操作の意味が分かります。


「3年前の写真に今書く」体験を成立させるには

機能としては作れた。 でも、「3年前の写真に今書く」という体験そのものを成立させるには、 3年前の写真にちゃんと出会わせる必要があります。

書くインターフェースだけ用意しても、ユーザーが昔の写真を掘りに行かなければ何も起きません。

ここで前に書いた「Pass(また今度)」と「再浮上」の設計が効いてきます。

  • 一度 Pass された写真が、しばらく経つと再浮上してくる
  • 数年前の写真も、ふとした瞬間に画面に戻ってくる
  • そのときの自分が「今ならこう書ける」と思ったら、書き足せる

つまり、「重ねる」機能は単独では成立しません。 Pass・再浮上・スキャン・詳細画面の全部が組み合わさって、 やっと「3年前の写真に今書く」体験になります。

このことに気づいたとき、「アプリの設計って、機能 1 個ずつじゃ足りないんだな」と思った。


実装の方針:エントリは独立、写真は親

データの形はとてもシンプルだ。

置き場所は端末の SQLite。photos と meanings の2表。photos写真は1行旅行の写真親。1枚photo_idmeanings言葉は複数行。行同士は繋がらない撮った当日1ヶ月後3年後層という入れ物は無い。後から足す言葉も最初の言葉も、同じ表の1行。
dart
// イメージ。実装の詳細は別記事に分けたい
class Entry {
  final String id;
  final String photoId;
  final String body;
  final DateTime writtenAt;
}

これだと、後から書く言葉も、最初に書いた言葉も、扱いに差がありません。 「最初の言葉が特別」みたいな構造にすると、後で「あ、最初のやつ消したい」となったときに困ります。

「全部対等」にしておくのが、後で楽になる設計だった。


詰まったところ:詳細画面で「層」を視覚化する

データは平らだけど、UI では「層が重なっている」感を出したい。

これが地味に難しい。 平らに並べると単なるリスト、立体的にすると読みづらい、その間を狙う必要があります。

同じ3つの言葉でも、保存と画面では形が違う。端末 SQLite の meanings平らな行。層の列は無い撮った当日1ヶ月後3年後詳細画面(描画だけ)新しいものが上。古くほど薄い撮った当日綴った日1ヶ月後綴った日3年後綴った日重ねと透明度は画面の描画。meanings に層の列は無い。

このあたりの「ちょっと重ねて貼ったみたいな見た目」を作るために、 別記事で書いた「ハンドメイド感」のテクニックがそのまま流用できた。



この記事で書かなかった話

  • エントリの編集/削除のフロー
  • エントリ単位の検索
  • 並び順を「綴った日」「撮影日」どっち基準にするか問題

このあたりは UI 寄りの細かい話なので別記事に分けたい。


学んだこと

  • 「重ねる」というメタファーが決まると、UI・データ・操作が一気に揃う
  • 機能は単独では成立しません。Pass・再浮上・スキャンが揃って初めて体験になる
  • データ上は「エントリは全部対等」にしておくと、後から自由が効く
  • 「層を見せる UI」は、完全に並べると味気なく、立体的すぎると読みにくい

大切な写真は、撮った瞬間で気持ちが固定されません。 時間が経つほど、別の意味を持ち始めます。 その変化をちゃんと拾えるアプリにしたかった。

「重ねる」というたった1つのコンセプトだけど、 これが綴Photo の中心にあるんだなと、書きながら改めて思った。


この記事は2026年4月時点の自分の理解と実装方針で書いています。アプリは継続開発中なので、現在の実装と細部が違っている可能性があります。