來吧!Flutter(14) — 訊息對話框
Published in
7 min readNov 30, 2020
即時通訊是大部分的人最常使用的 App 之一。在這些 App 當中,經常會使用對話框的圖示來表示一則訊息,那麼,我們該如何用 Flutter 來產生這訊息對話框呢?
第一部分:ListView
Message Entity
第一步,我們先設計Message Entity。
在這個 Message Entity 中,有兩個屬性,一個為 content
用來存放訊息的內容,另一個為 isMe
用來表示是否為自己發送的訊息,若為自己發送的訊息,則顯示於右方,否則顯示於左方。
第二步,填入假資料。
ListView
第三步,利用 ListView
來產生顯示的訊息列表。
為了呈現我的訊息顯示在右側,其他人的訊息顯示在左側,我先利用 Container
將 Text
包起來,並依照 isMe
的值來決定 alignment
的值。
到目前為止,已經完成顯示訊息,並且依照訊息的所有者顯示於相對應的位置。
第二部分:Container + BoxDecoration
接者,我們希望能夠將每一個訊息都填上顏色,每個訊息框都有圓角。
如下圖:
先回顧一下訊息是怎麼繪製的:
- 利用 Container 將 Text 包起來,並且依照
isMe
來決定 Text 的位置。 - 因為沒有設定外圍的 Container 寬度,所以 Container 的寬度是螢幕的寬度,所以如果直接在 Container 設定顏色,則會整個寬度都被填滿顏色。如下圖:
那麼,該如何將 Text 外面加上一層外框呢?
方法: 在 Text 外面加上一層 Container ,並且設定其寬度。
設定內部 Container :
- 寬度設定為畫面寬度的一半:
width: MediaQuery.of(context).size.width/2
- 利用
BoxDecoration
設定填滿的顏色,以及圓角。
第三部分:CustomPainter
在第二部分,使用 Container 加上 BoxDecoration 就可以繪製出一個具有圓角的訊息框。
如果希望能夠替每一個對話框加上一個小角,讓訊息框更美觀,如下圖:
Step1:新建繼承 CustomPainter 的類別
- 在 CustomPainter 中,有兩個方法需要實作:
paint(Canvas canvas, Size size)
:用來描述要如何繪製。shouldRepaint(CustomPainter oldDelegate)
:用來決定是否需要重繪。
Step2:將預計要繪製的樣式分割如下:
- 紅色虛線框起來的部分:圓角對話框。
- 綠色虛線框起來的部分:對話框的角,寬度為 10.0 px。
Step2–1:圓角對話框
- paint 方法中,第一的參數
Canvas
是用來繪製圖形重要的參數,裡面包含了許多繪製的方法。
- 利用 Canvas 的 方法
drawRRect
來繪製圓角長方形。
- 在 drawRRect 方法中,需要帶入兩個參數:RRect 以及 Paint。
→ RRect 是圖形的樣子,Paint 是圖形的風格。
- 利用 RRect 類中
fromLTRBAndCorners
建構子來設定圓角長方形的大小,這邊需要注意的是,因為是實際繪製的位置,由於綠色部分寬度為 10.0 px ,所以我們的圖形的最左側為 10.0。最右側則為size.width
。 fromLTRBAndCorners
預設的角落都是沒有圓角的,所以我們可以針對需求設定圓角的半徑,這邊我對每一個角落都設定半徑為 10.0 的圓角。
Step2–2:對話框左側的角。
- 將左側角各個點標示如上,我打算將角繪製在高度三分之一的位置,並且其高度為 10.0 px。
- 利用
Path
,我們可以按照需求繪製所需要的圖形。
path.moveTo
將繪製點移動到 (0, 1/3 的高度)path.lineTo
繪製一條直線到 (10.0, 1/3 的高度)path.lineTo
繪製一條直線到 (10.0, 1/3 的高度 + 10.0)canvas.clipPath(path)
將 Canvas 裁減其他的區域 (只保留這個區域)
- 接者,利用
canvas.drawRect
填滿左側區域。
drawRect
會與clipPath
產生出一個角。
Step 3:將內部 Container 用 CustomPaint 包起來
- 利用
CustomPaint
將 Container 包起來,並且將 ChatBubble() 設為painter
的參數。 - CustomPaint 會將子 Widget 的資訊傳入
ChatBubble
中,所以在 ChatBubble 就能取得其尺寸,並繪製於指定的位置。
- 眼尖的朋友應該有發現,右邊的對話框的角應該是在右邊而不是在左邊,這個部分讓各位朋友想想看該怎麼處理。
小結
- 如果要產生一個訊息列表,我們可以使用 ListView 來建立。利用
ListView.builder
我們可以將所需要繪製的內容填寫在itemBuilder
中,ListView 就會依照每一個 index 去取得相對應的資料填入。 - 要替 Text 加上外框,我們可以使用
Container
包在 Text 的外面,接者在 Container 內部設定 decoration ,如此就可以加上簡單的外框。 - 如果需要較為複雜的外框,我們可以利用
CustomPainter
類,繼承 CustomPainter 之後,我們可以覆寫paint
方法來繪製我們預期的樣子。
謝謝收看
Github: https://github.com/andyludeveloper/flutter_chat_bubble_example