好不好看,是那些小地方決定的
大面板再怎麼磨,抓住視線的永遠是某個小東西:一個被切成兩半的字、一圈被削掉的光暈、 一格擠成一團的快捷格。2026-09-13 有人指出四件這樣的事,修正做在控制項與佈景主題裡, 而不是示範畫面裡,所以每一個畫面都得到同樣的結果。
| 看到什麼 | 原因 | 修法 |
|---|---|---|
導覽標記的 Done 變成 Don/e |
開了換行的按鈕會從最小寬度中扣掉文字寬度 — 一被擠壓就從字中間斷開 | GoStyle.fit_words():單一個字永遠不換行;多個字可以換行,但最長的那個字一定塞得下 — 判斷依據是實際顯示的文字,而不是翻譯鍵,而且語言變更時表單會重新套用 |
| 整行寬的按鈕,左側的光暈在垂直方向被切掉 | 捲動容器一律在自己的邊緣裁切,沒有例外。只有右側因為捲軸留出的溝槽而倖免 | GoScroll 借用上層的內距,把自己的邊緣往外推 12dp,再在內側還回去 — 內容原地不動 |
| 時間、圖示與數量在一格快捷格裡上下堆成三層 | 48dp 裡塞了三列 | 圖示放大置中,快速鍵在左上,數量當成右下的徽章,剩餘時間則是壓在圖示上的徽章 — 徽章面板來自外觀的 badge_box() |
| 下拉選單很平,看不出選了哪一個 | 項目的滑過狀態用的是按鈕面板;選項記號則是引擎那個很淡的預設圖案 | 專用的滑過面板(柔和的強調色著色)、與核取方塊相同的選項圖案,以及為觸控加高的項目高度 |
用 GoStyle.icon_button(icon, action, -1, tooltip_key) 給只有圖示的按鈕一段說明 —
給滑鼠使用者的工具提示,和給螢幕閱讀器的無障礙名稱,都來自這同一個值。
工具提示是 gohud 自己畫的:引擎預設的那個在寬度計算出錯時,會把文字拆成一行一個字
(實測寬度只有 1dp)。
導覽標記的卡片會避開固定元素
橫向時,這張卡片以前會被送到畫面最上或最下的邊緣 — 那裡剛好就是頁首與 HUD
零件的地盤;在示範裡,它就壓在頁首的 → × 上。現在它會與目標保持齊高,
繞開任何有保留空間的 GoHudAnchor,也可以透過 keep_clear
告訴它還要避開什麼。它會用最短的距離移開障礙物,同時不遮住目標;
當螢幕小到怎麼挪都躲不掉時,它就留在原地 — 重疊總比消失好。
它的層次感 — 讓它讀起來像在頁面之上 — 來自外觀的旋鈕
(float_shadow_size、float_shadow_lift、float_shadow_alpha;切角風格的外觀則用 float_glow_size)。
tour.keep_clear = [header_bar, toolbar] # 不是錨點的固定元素
有滑鼠與鍵盤的畫面
手指沒有滑過狀態。只照著行動裝置開發,就會有兩個只出現在桌機的狀態沒被檢查 —
而其中一個確實壞了:gohud 的焦點外框在主要按鈕上是看不見的。面板是強調色,
外框也是同一個色:1.00:1,等於把同樣的顏色畫在自己身上。
用鍵盤移動時,根本看不出自己在哪裡。
實心按鈕(GoPrimaryButton、GoDangerSolidButton)使用的外框
與自己的面板形成對比 — 深色佈景主題上用深色,淺色上用白色,科幻風格則是深色的
瞄準框角。對比檢查器量的是焦點外框與它所在的面板,所以換了調色盤這條規則依然成立
(WCAG 2.4.11 要求焦點指示器達到 3:1)。
HUD 控制項
GoHudAnchor — 九個位置
它會尊重安全區域與邊界留白。給它一個 landscape_spot,橫向時它就會換位置 —
直向時待在底部中央的操作鍵,橫向可以改到右下。
別讓內容跑到 HUD 底下
當一個會捲動的畫面和 HUD 共用螢幕時,內容會滑到它下面,兩邊的文字互相重疊, 最後誰都讀不出來。這在這個附加元件裡發生過兩次:輸入欄的提示文字被擠在快捷格中間, 以及設定裡的切換開關的旋鈕落在生命量條上。
form.avoid_hud = true # 避開每一個顯示中的 GoHudAnchor
joystick_anchor.reserve_space = false # …但只在手指底下才出現的那些除外
每個矩形都往損失面積最小的方向避開。右上角的量條,在直向手機上往下繞 (高度的 13%),在橫向則往側邊繞(寬度的 21%) — 橫向時若改成垂直避開,會吃掉螢幕的 27%。 已經讓出去的地盤,會先扣掉,再去量下一個矩形。
HUD 零件彼此也會撞在一起
九個位置只是把畫面分好;它們並不保證零件彼此不相碰。一條很寬的訊息條擺在 上方中央,就正好壓在右上的生命量條上,把數值遮住 — 你根本讀不到還剩多少血。
notice_anchor.avoid_peers = true # 停在固定 HUD 下方
notice_anchor.reserve_space = false # 顯示期間也不會推擠頁面
它只在垂直方向讓開 — 連橫向也一起挪的話,置中的提示訊息每次出現的位置就不一樣。 而且它只避開那些本身不會讓開的零件:如果雙方都讓,兩者就會永遠交換位置。
GoBar — 生命、魔力、經驗
var hp := GoBar.new()
hp.label_text = "HP"
hp.ink = GoUi.color(GoTheme.DANGER_FILL) # 只用於填色的 token
hp.set_values(320, 500) # "320 / 500"
數值變化會在 0.18 秒內緩動 — 一條直接跳掉的生命量條,說不出你被打得多重。
reduce_motion 會讓它立即完成。大數字會縮寫成 12.3k,
讓量條的寬度不會隨著位數增減而抖動。
GoSlot — 一格快捷格
圖示、數量、冷卻與快速鍵都在同一個面上。把徽章掛在小圓圈外面, 會讓每一格寬度都不一樣,整列就歪歪扭扭。
touch_peers
讓它們知道彼此的存在。
keyboard_focus 預設是關的,這樣八格一列的快捷格才不會卡在鍵盤使用者與 Tab 順序上
所有設定控制項之間。只有在鍵盤或遊戲手把是唯一輸入方式時才打開它。
GoJoystick — 虛擬搖桿
| 模式 | 行為 |
|---|---|
FIXED | 永遠在同一個地方 — 不用看也找得到 |
FOLLOW | 出現在拇指按下的位置 |
RELATIVE | 出現之後繼續跟著拇指 — 長時間移動比較舒服 |
moved 傳出來的 Vector2 長度介於 0–1,所以可以直接乘上速度;
它不會隨螢幕大小或 DPI 改變。
GoIconButton — 看起來小,按起來大
touch_peers。