National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 08

Flex Message

用 JSON 排版一張卡片:bubble、box、text、button
Interaction實作 30 minute(s)

Learning Objectives

  • 說出 container、block、component 的層次,以及 bubble 四個 block 的順序
  • 用 box 的 layout、flex、margin、spacing 排出需要的版面
  • 用 Python 字典組出 Flex Message,以 FlexContainer.from_dict 送出,並寫出有意義的 alt_text
  • 依資料用迴圈產生多張卡片,放進 carousel,並處理官方上限與沒有資料的情況

範本排不出來的版面

上一課的 Buttons、Carousel 範本格式是固定的:一個標題、一段文字、幾顆按鈕。想做一張左邊是欄位名稱、右邊是內容的課程資訊卡,範本就排不出來。

Flex Message 讓你用 JSON 自己排版。它分成三層:

層次 是什麼 這一課會用到
Container(容器) 整則訊息的最外層 bubble(一張卡片)、carousel(多張卡片左右滑動)
Block(區塊) 一張卡片裡的區域,由上到下 header、hero、body、footer,都可以省略,每種最多一個
Component(元件) 區塊裡的東西 box、text、button、image、separator

header、body、footer 裡面放的一定是 box;hero 常放圖片。box 可以放其他元件,也可以再放 box,版面就是這樣一層層組出來的。

在 Python 裡,JSON 就是字典和串列。FlexContainer.from_dict(字典) 把它轉成 SDK 的物件,再放進 FlexMessage。

逐步看:一張卡片怎麼送出去

卡片只是一個字典常數 CARD。按播放,注意 on_text 裡只多了一行:把字典轉成物件,包成 FlexMessage。最後印出的是模擬平台實際收到的內容。

box 決定元件怎麼排

每個 box 都要設定 layout,也就是裡面的元件往哪個方向排:

layout 排列方式 常見用途
vertical 由上往下 整個 body、一段段內容
horizontal 由左往右 「欄位名稱+內容」同一列
baseline 由左往右,文字的基線對齊 字級不同的文字放同一列、小圖示加文字

baseline 裡只能放 text、icon 這類元件,不能放 button、image、separator,也不能再放 box。

幾個調整版面的屬性:

屬性 寫在哪裡 作用
flex 子元件 佔幾份寬度或高度。官方預設值:horizontal 裡是 1(平均分配),vertical 裡是 0(依內容大小)
spacing 父層的 box 所有子元件之間的間距
margin 子元件 這個元件前面的間距,會蓋過父層的 spacing
wrap text 預設 false,文字太長會被截斷;要換行就設 True
size、weight、color text 字級(xs、sm、md、lg、xl…)、粗細(bold)、顏色(#RRGGBB)

要畫分隔線用 separator。舊教材常見的 filler(佔空白的元件)官方已標示棄用,留白請改用 margin、spacing、flex。

逐步看:把重複的版面寫成函數

課程資訊卡有很多列長得一樣,每一列寫一次會很長。既然是字典,就可以用函數產生。這個範例沒有機器人,只看字典怎麼組、SDK 怎麼轉。

互動練習:排一張課程資訊卡

按「▶ 啟動機器人」,傳「卡片」。上方灰色的框是 hero 的圖片:模擬手機不載入任何外部圖片,一律畫成佔位框。真實環境的圖片網址要用 HTTPS,而且要是連得到的公開網址,模擬平台不檢查這些。

模擬手機是簡化的呈現,字型、間距和比例都和 LINE App 不同,所以這裡只用來確認結構對不對。完整效果請用這一課最後介紹的官方工具比對。

改程式時,修改 CARD,再按「存檔並重新啟動」。Flex 的 JSON 很長,「呼叫 LINE API」面板會拉得很長,任務清單在面板下方;看完切到別的面板就會收起來。

想一想:版面

1.

一個 bubble 同時有四個 block,由上到下的順序是?

2.

想讓「學分」和「3」排在同一列,左窄右寬。應該怎麼寫?

3.

alt_text 的用途是什麼?

第 1 次作答

互動練習:課程清單輪播

這次卡片由 COURSES 產生。傳「課程」後,手機上的卡片可以左右滑動。按鈕是 postback 動作,使用者看不到 data,到「收到的 Webhook」面板才看得到。

想一想:資料與上限

1.

這段程式會印出什麼?

COURSES = [{'name': 'A'}, {'name': 'B'}, {'name': 'C'}]

def bubble(c):
    return {'type': 'bubble', 'body': {'type': 'box', 'layout': 'vertical',
            'contents': [{'type': 'text', 'text': c['name']}]}}

carousel = {'type': 'carousel', 'contents': [bubble(c) for c in COURSES[:2]]}
print(len(carousel['contents']), carousel['contents'][-1]['body']['contents'][0]['text'])
2.

查詢結果有 30 筆,機器人想用 carousel 列出。比較合適的做法是?

第 1 次作答

在官方工具確認實際樣子

模擬手機只畫出結構。實際的字型、留白、圖片比例,要用 LINE 官方的 Flex Message Simulator 確認(要登入 LINE Developers 帳號,官方教學)。

常見的工作方式:

  1. 在 Simulator 裡拉出想要的版面
  2. 複製它產生的 JSON,用 json.loads 轉成字典
  3. 把會變動的部分(課程名稱、時間)換成變數,寫成像 course_bubble 這樣的函數

官方也提醒,同一則 Flex Message 在不同的裝置、作業系統、LINE 版本、語言與字型下,看起來可能不同,所以重要的訊息要放在文字裡,不要只靠排版傳達。

重點整理

  • Flex Message 分三層:container(bubble、carousel)、block(header、hero、body、footer)、component(box、text、button、image、separator)
  • box 的 layout 決定方向;flex 分配比例,spacing 寫在父層,margin 寫在子元件
  • 用字典組版面,FlexContainer.from_dict 轉成物件,alt_text 必填
  • 重複的版面寫成函數,依資料用迴圈產生;carousel 最多 12 個 bubble,沒有資料時改回文字
  • 模擬手機只看結構,實際樣子用 Flex Message Simulator 確認

到目前為止,機器人每次都只看眼前這句話。下一課讓它記得使用者上一句說了什麼。

這一課完成了!
Next lesson:記住對話:狀態與 SQLite
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。