メッセージ一覧画面(LINE 風トーク)|Android デザイン実践勉強会
サービスにおいて、今やチャット機能は不可欠なようです。最近は、依頼される殆どのアプリ開発で、「LINE のようなトークルーム」を実装しています。そのまま隠しもせずに「LINE 風のメッセージ画面」と仕様書に堂々と書いてある程です。
勿論、寸分違わず、ということではありませんが、ほぼ LINE 風のデザイン指示で、毎度、同じようなレイアウト実装を行っているので、ならば敢えて、LINE のデザインを勉強してみようじゃないか、と思います。
LINE トークを構成する各サイズを分析
余白やコンポーネントの各サイズを調査し、以下に書き込みました。単位は dp。
「W 360 dp x H 70 dp」がトーク一項目のサイズです。
複雑な構成ではありませんが、少し特徴的です。レイアウト実装時に、どうやって実現するのかな、と勉強になる箇所も少々ありますので、実装のポイントも後述します。
LINE トークの気になる特徴
「日時と未読数」を表示している領域が、固定幅(86dp)になっているようで、例えば「14:00」という短い日付テキスト表示時も、メッセージ領域が不変で右側に伸びていないのが特徴的でした。
メッセージ幅が可変であれば、もっとユーザにメッセージを多く見せられると思いますが、そこは好き嫌いで、LINE デザイナーの拘りなのでしょう。私なら、少しでもユーザに多くのメッセージを見せられるように、可変にします。Google 「メッセージ」アプリがまさにそうです。
また、「日時」の文字サイズですが、「12sp」を下回る小ささで、Android では、あまりに小さ過ぎる文字サイズは、以下の警告を出してしまいます。
Avoid using sizes smaller than 12sp
12sp 未満のサイズの使用は避けてください
LINE に酷似したメッセージ一覧画面を実現
Android の警告に則り、設定する最小の文字サイズを「12sp」として構成して、概ね、実現できました。配色に関しては、勉強の対象外としています。
この全実装(環境一式)は後述にて公開します。
さて、勉強になった実装を以下に解説します。
その前にコーヒーブレイク
次は実装レベルの細かい勉強になるので、神経を使うその前に、コーヒーブレイクしておきます。最近、ラブコメ漫画で注目しているのは「おとなりに銀河」です。
情熱が真っ直ぐでイイです。こういう感じ、どんどん失っていくなあ。
丸イメージ画像は ShapeableImageView を利用
ShapeableImageView はマテリアル・コンポーネントです。簡単に Shape を設定できます。
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/talk_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginVertical="10dp"
android:background="@color/teal_700"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="ContentDescription" />
イメージ画像を円にするだけなら、以下のように、とても簡単に実現できます。
binding.talkImage.shapeAppearanceModel =
ShapeAppearanceModel
.builder()
.setAllCornerSizes(ShapeAppearanceModel.PILL)
.build()
この丸い画像を実現する為だけに、外部ライブラリを導入しているケースも多いので、今後はこちらに乗り換えた方が楽になるでしょう。
layout_constraintVertical_chainStyle で「鎖」関係を意識
ひと目見て、「名前」と「メッセージ」は、上下にくっつけて、その状態で縦方向に中央配置したい、とパッと思いつくかもしれません。
しかし、意外と、その実現方法が思いつかないものです。
これは知っていれば、「layout_constraintVertical_chainStyle="packed"」で簡単に実現できます。縦(Vertical)に並んでいる View をくっつける(packed)という指示です。
<TextView
android:id="@+id/talk_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@{data.name}"
android:textSize="16sp"
android:lines="1"
android:ellipsize="end"
app:layout_constrainedWidth="true"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/talk_content"
app:layout_constraintStart_toEndOf="@id/talk_image"
app:layout_constraintEnd_toStartOf="@id/talk_mute" />
<TextView
android:id="@+id/talk_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{data.content}"
android:textSize="14sp"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="@id/talk_name"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@id/talk_name"
app:layout_constraintEnd_toStartOf="@id/talk_date" />
これは横(Horizontal)にも勿論、応用が可能です。
「名前」と「ミュート画像」をくっつけて、「名前」が長くなっても「日時」を超えないようにする横並びのレイアウトを考えつくでしょう。
このケースは「layout_constraintHorizontal_chainStyle="packed"」が活躍します。加えて、「layout_constrainedWidth="true"」で制約を超えてしまわないように指定します。指定しないと「日時」を重なってしまいます。
<TextView
android:id="@+id/talk_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@{data.name}"
android:textSize="16sp"
android:lines="1"
android:ellipsize="end"
app:layout_constrainedWidth="true"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/talk_content"
app:layout_constraintStart_toEndOf="@id/talk_image"
app:layout_constraintEnd_toStartOf="@id/talk_mute" />
<ImageView
android:id="@+id/talk_mute"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginStart="4dp"
android:src="@drawable/outline_volume_off_24"
app:layout_constraintTop_toTopOf="@id/talk_name"
app:layout_constraintBottom_toBottomOf="@id/talk_name"
app:layout_constraintStart_toEndOf="@id/talk_name"
app:layout_constraintEnd_toStartOf="@id/talk_date" />
<TextView
android:id="@+id/talk_date"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="end|center_vertical"
android:text="@{data.date}"
android:textSize="12sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
「layout_constraintHorizontal_bias="0.0"」を設定して、「名前」と「メッセージ」が中央に配置されるのを抑止しています。「0.0」は、バイアスが無い状態で、左端にくっつきます。
レイアウト全容と環境一式
この全実装(環境一式)を以下に公開します。今後、トーク画面を開発する際、この実装をベースに改造すると、だいぶ楽になると思います。
ここから先は
¥ 390
この記事が参加している募集
この記事が気に入ったらチップで応援してみませんか?