FlutterでメッセージアプリのトークっぽいUIを作る【リスト編】


メッセージアプリって意外と作る機会なかったので、Flutterの勉強がてら作ってみました。
※今回は、メッセージを表示するリストUIのみです。

扱うメッセージのモデル

メッセージで扱う情報は以下のモデルを定義しておきます。
このモデルのリストを表示します。この定義がベストとは限りませんのでご了承ください。

class ChatMessageModel {
  final String avatarUrl; //ユーザのアイコンURL
  final String name;      //名前
  final String datetime;  //メッセージの日時
  final String message;   //メッセージ本文
  final bool isMine;      //メッセージの自身のものか?

  ChatMessageModel({this.avatarUrl, this.name, this.datetime, this.message, this.isMine});
}

メッセージUIの大枠を作る

今回作るUIのイメージはLINEのトークといったメッセージをやりとりするUIです。
FlutterのWidgetであるListViewListTileを使ってみます。

ListViewでListTileを並べる

ListViewとは

よく使われるスクロールウィジェットです。
子要素をスクロールする縦方向に表示することができます。
表示する子要素の量や動的か固定かによって、使うべきコンストラクタが変わります。今回は表示するリストの数が少ないのでデフォルトのままでいきます。
for文を使って子要素を並べる実装にします。

ListTileとは

アイコンや1行から3行までのテキストなどを、マテリアルデザインのリスト仕様で配置できるウィジェットです。
基本的にデザインが出来上がってるので、プロパティに表示するものを設定するという親切設計です。
プロパティのtitleにメッセージ本文、subtitleにユーザのアイコン・名前、メッセージの時刻を表示してみます。
ListViewの子要素にこのListTileを並べます。

コーディングしたものがこちら

ListView(
  children: [
    for (int index = 0; index < widget.chatMessageList.length; index++)
      Card(
        child:ListTile(
          title:Text(widget.chatMessageList[index].message),
          subtitle: Row(
            children: <Widget>[
               CircleAvatar(
                 backgroundImage:  NetworkImage(widget.chatMessageList[index].avatarUrl),
                 radius: 10.0,
               ),
               Text(widget.messageList[index].name + widget.chatMessageList[index].datetime),
           ]
),),),],)

コード中にCardとありますが、これもウィジェットです。今はListTileの外枠のデザインのために使っています。

ここまでのUIはこんな感じ。これだとまだスレっぽいですね。

トークっぽいUIにスタイルを調整する

スタイルを調整してトークっぽいUIにします。
Cardのプロパティにmarginを設定します。
marginは、CSSでもある様に要素の周りのマージンを設定するものです。
モデルで定義したisMineを使って、設定するマージンを切り替えます。

margin: widget.messageList[index].isMine 
  ? EdgeInsets.only(top: 5.0, left: 90.0, bottom: 5.0, right: 8.0) //自分のメッセージであれば右寄せる
  : EdgeInsets.only(top: 5.0, left: 8.0, bottom: 5.0, right: 90.0) //自分以外は左に寄せる

ListTileのRowmainAxisAlignmentを追加します。
Rowは横並びに子要素を表示するウィジェットです。ユーザのアイコン・名前、メッセージの時刻
mainAxisAlignmentはフレックスボックスの様なレイアウト設定ができます
こちらもisMineを使って設定を切り替えます。

mainAxisAlignmentはついてはこちらがすごく参考になりました。

mainAxisAlignment: widget.messageList[index].isMine 
  ? MainAxisAlignment.end   //アイコン・名前、メッセージの時刻を右寄せにする
  : MainAxisAlignment.start //アイコン・名前、メッセージの時刻を左寄せにする

入れたものがこちら

ListView(
  children: [
    for (int index = 0; index < widget.chatMessageList.length; index++)
      Card(
        margin: widget.messageList[index].isMine 
          ? EdgeInsets.only(top: 5.0, left: 90.0, bottom: 5.0, right: 8.0)
          : EdgeInsets.only(top: 5.0, left: 8.0, bottom: 5.0, right: 90.0),
        child:ListTile(
          title:Text(widget.chatMessageList[index].message),
          subtitle: Row(
            mainAxisAlignment: widget.messageList[index].isMine 
              ? MainAxisAlignment.end
              : MainAxisAlignment.start,
            children: <Widget>[
               CircleAvatar(
                 backgroundImage:  NetworkImage(widget.chatMessageList[index].avatarUrl),
                 radius: 10.0,
               ),
               Text(widget.messageList[index].name + widget.chatMessageList[index].datetime),
           ]
),),),],)


LINEのトークっぽいUIになりました。全然遠いですけどね笑
まだまだ作成中ですがコードはこちらに置いてあります。
https://github.com/taka-guevara/FlutterMessangerApp

次回予告

メッセージのフォームと送信ボタン周りを作ってみます。
https://qiita.com/guevara-net/items/b40f96c1329d239197fd

Firebaseかslackと連携してみたい(願望)