iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 28
0
Mobile Development

30天手滑用Google Flutter解鎖Hybrid App成就系列 第 28

30天Flutter手滑系列 - 聊天室開發(Chat Room)(8)

前一天的文章30天Flutter手滑系列 - 聊天室開發(Chat Room)(7),完成了TextFieldIconButton的連動,今天來設計如何把訊息填入主畫面中。

建立訊息列表

首先來到ChatPageState,宣告一個陣列,準備用來儲存每次輸入的訊息內容。

class ChatPageState extends State<ChatPage> {
final TextEditingController _chatController = new TextEditingController();
final List<Widget> _message = [];   // 建立一個空陣列

...
}

然後到原本預留的Expanded內,新增一個ListView,將這個陣列綁定ListView

Expanded(
  child: ListView.builder(
    padding: new EdgeInsets.all(8.0),
    itemBuilder: (context, index) => _messages[index],
    itemCount: _messages.length,
  ),
)

寫入訊息

再來我們需要透過setState,把每次訊息輸入後的值存入這個陣列,使其能夠顯示在畫面上。

void _submitText(String text) {
    _chatController.clear();  // 清空controller資料
    setState(() {
      _messages.insert(0, Container(child: Text(text)));  // 把文字存入陣列0的位置
    });
  }

到目前為止,我們來看一下效果。
https://upload.cc/i1/2019/10/05/zEZK31.gif

可以看到有兩個明顯問題:

  1. 訊息應該由下往上
  2. 一般來說,自己送出的訊息應該靠畫面右方。

第1點可以在ListView內加入reverse: true

Expanded(
  child: ListView.builder(
    padding: new EdgeInsets.all(8.0),
    reverse: true,  // 加入reverse,讓它反轉
    itemBuilder: (context, index) => _messages[index],
    itemCount: _messages.length,
  ),
)

第2點可以在Text外層包一個Container,並用alignment: Alignment.centerRight,讓他靠右對齊。

_messages.insert(0, Container(child: Text(text), alignment: Alignment.centerRight));

修正後如下圖
https://upload.cc/i1/2019/10/05/oCWcsR.gif


模組化組件

在軟體開發過程中,如果是複雜的UI,很常會被設計成獨立的component,在這個APP中的訊息就是很單純的UI(指沒有邏輯行為),我們來將其模組化。

首先在/lib/下,建立一個components資料夾,並且新增一個messageBox.dart的檔案。

為了放置頭像在訊息右邊,我們用Row去排列,因此原先在Containeralignment就可以拿掉了。
要讓Row內的children都靠右,需要加入

mainAxisAlignment: MainAxisAlignment.end

然後再用一個Flexible包裝訊息長度,使其可以根據內容長度去彈性延伸長度。
FlexibleText之間再加入一個Container用來調整其樣式。
Text中,為了怕訊息太長爆掉,可以加入overflowmaxLines

overflow: TextOverflow.ellipsis,
maxLines: 5,

小提示
ListColumn中,若要讓Text的換行起作用,需要加入ExpandedFlexible包裝

https://upload.cc/i1/2019/10/05/UftP06.gif

完整程式碼如下

import 'package:flutter/material.dart';

class MessageBox extends StatelessWidget {
  final String text;

  MessageBox({Key key, this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 10.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Flexible(
            child: Container(
              color: Colors.pink,
              padding: EdgeInsets.all(10.0),
              child: Text(text,
                  overflow: TextOverflow.ellipsis,
                  maxLines: 5,
                  style: TextStyle(fontSize: 18.0, color: Colors.white)),
            ),
          ),
          Icon(Icons.person, size: 32)
        ],
      ),
    );
  }
}


總結

基本的對話介面已經完成了,剩下就是美化它或是加強功能。明天要回到頭痛的Firebase部分,希望能在完賽前把真正的即時訊息完成。


上一篇
30天Flutter手滑系列 - 聊天室開發(Chat Room)(7)
下一篇
30天Flutter手滑系列 - 聊天室開發(Chat Room)(9)
系列文
30天手滑用Google Flutter解鎖Hybrid App成就30

尚未有邦友留言

立即登入留言