Kotlin Android 基礎知識 10.3:適合所有人的設計

這個程式碼研究室是 Android Kotlin 基礎知識課程的一部分。如果您按部就班完成程式碼研究室,就能充分體驗到本課程的價值。所有課程程式碼研究室都列在 Android Kotlin 基礎知識程式碼研究室到達網頁

簡介

無論是為了興趣還是商業目的而開發應用程式,讓最多使用者都能使用應用程式都是合理的做法。達成這項目標的方法有很多種。

  • 支援 RTL 語言。歐洲和許多其他語言都是從左到右閱讀,因此源自這些語言代碼的應用程式通常會設計成適合這些語言。許多其他語言 (例如阿拉伯文) 的閱讀方向是從右到左,且有大量使用者。讓應用程式支援從右到左 (RTL) 語言,增加潛在目標對象。
  • 掃描無障礙功能。猜測他人使用應用程式時的體驗可能會有缺點。 無障礙功能檢查工具應用程式可分析您的應用程式,找出可改善無障礙功能的部分,讓您不必再反覆猜測。
  • 採用 TalkBack 適用的設計,並提供內容說明。視障比您想像中更常見,許多使用者 (不只是盲人) 都會使用螢幕閱讀器。內容說明是螢幕閱讀器在使用者與畫面元素互動時朗讀的詞組。
  • 支援夜間模式。對許多視障使用者來說,變更螢幕色彩可提升對比度,協助他們以視覺方式操作應用程式。Android 支援夜間模式,您應一律支援夜間模式,為使用者提供預設螢幕色彩的簡單替代方案。

在本程式碼研究室中,您將探索這些選項,並為 GDG Finder 應用程式新增支援。

您也會瞭解如何在 Android 應用程式中使用動態磚,讓應用程式更具吸引力,同時維持無障礙功能。

必備知識

您必須已經熟悉下列項目:

  • 如何建立含有活動和片段的應用程式,並在片段之間瀏覽及傳遞資料。
  • 使用檢視區塊和檢視區塊群組配置使用者介面,特別是 RecyclerView。
  • 如何搭配建議的架構使用架構元件 (包括 ViewModel),建立結構完善且有效率的應用程式。
  • 資料繫結、協同程式,以及如何處理滑鼠點擊。
  • 如何連上網際網路,並使用 Room 資料庫在本機快取資料。
  • 如何設定檢視區塊屬性,以及如何將資源擷取至 XML 資源檔案,並從中取用資源。
  • 如何使用樣式和主題自訂應用程式的外觀。
  • 如何使用 Material 元件、維度資源和自訂顏色。

課程內容

  • 如何盡可能讓更多使用者使用您的應用程式。
  • 如何讓應用程式支援從右到左書寫 (RTL) 的語言。
  • 如何評估應用程式的無障礙功能。
  • 瞭解如何使用內容說明,讓應用程式更適合搭配螢幕閱讀器使用。
  • 如何使用方塊。
  • 如何讓應用程式支援深色模式。

學習內容

  • 評估及擴充指定應用程式,使其支援 RTL 語言,進而提升無障礙功能。
  • 掃描應用程式,判斷哪些地方可以改善無障礙功能。
  • 為圖片使用內容說明。
  • 瞭解如何使用可繪項目。
  • 在應用程式中新增夜間模式功能。

GDG 搜尋器入門應用程式會運用您在本課程中學到的所有知識。

應用程式使用 ConstraintLayout 配置三個畫面。其中兩個畫面只是版面配置檔案,您將用來探索 Android 上的顏色和文字。

第三個畫面是 GDG 搜尋器。GDG (Google Developer Group) 是開發人員社群,專注於 Google 技術,包括 Android。世界各地的 GDG 會舉辦聚會、研討會、學習營和其他活動。

開發這個應用程式時,您會使用 GDG 的實際清單。尋找器畫面會使用裝置的位置資訊,依距離排序 GDG。

如果幸運的話,您所在地區有 GDG,可以查看網站並報名參加活動!GDG 活動是認識其他 Android 開發人員的好機會,您也可以學習本課程未涵蓋的業界最佳做法。

以下螢幕截圖顯示應用程式在本程式碼研究室中從頭到尾的變化。

由左至右 (LTR) 和由右至左 (RTL) 語言的主要差異在於顯示內容的方向。當 UI 方向從 LTR 變更為 RTL (或反之) 時,通常稱為鏡像。鏡像功能會影響大部分的畫面,包括文字、文字欄位圖示、版面配置,以及含有方向的圖示 (例如箭頭)。其他項目不會鏡像顯示,例如數字 (時鐘、電話號碼)、沒有方向的圖示 (飛航模式、Wi-Fi)、播放控制項,以及大多數圖表。

全球有超過 10 億人使用 RTL 文字方向的語言。Android 開發人員遍布全球,因此 GDG Finder 應用程式必須支援 RTL 語言。

步驟 1:新增 RTL 支援功能

在本步驟中,您要讓 GDG Finder 應用程式支援 RTL 語言。

  1. 下載並執行 GDGFinderMaterial 應用程式 (本程式碼研究室的範例應用程式),或繼續使用先前程式碼研究室的最終程式碼。
  2. 開啟 Android 資訊清單。
  3. <application> 區段新增以下程式碼,指定應用程式支援 RTL。
<application
        ...
        android:supportsRtl="true">
  1. 在「Design」分頁中開啟 activity_main.xml
  2. 在「預覽的語言代碼」下拉式選單中,選擇「從右至左預覽」。(如果找不到這個選單,請加寬窗格或關閉「屬性」窗格,即可找到)。

  1. 在「Preview」中,請注意「GDG Finder」標題已移至右側,其餘畫面大致維持不變。整體而言,這個畫面還算合格。但文字檢視區塊中的對齊方式現在是錯誤的,因為文字是向左對齊,而不是向右對齊。

  1. 如要在裝置上啟用這項功能,請在裝置或模擬器的「設定」中,選取「開發人員選項」中的「強制使用從右至左版面配置」。(如需開啟「開發人員選項」,請找出「版本號碼」並點選,直到系統顯示您是開發人員的訊息為止。(這會因裝置和 Android 系統版本而異)。

  1. 執行應用程式,並在裝置上確認主畫面與「預覽」中的畫面相同。請注意,FAB 現在已切換至左側,而「漢堡」選單則在右側!
  2. 在應用程式中開啟導覽匣,然後前往「搜尋」畫面。如下所示,圖示仍位於左側,但不會顯示任何文字。結果發現文字位於螢幕外,在圖示左側。這是因為程式碼在檢視區塊屬性和版面配置限制中,使用了左/右螢幕參照。

步驟 2:使用「start」和「end」取代「left」和「right」

即使文字方向改變,畫面上的「左」和「右」也不會變動 (以面對螢幕的方向為準)。舉例來說,layout_constraintLeft_toLeftOf 一律會將元素的左側限制在螢幕左側。以您的應用程式為例,RTL 語言的文字會超出畫面,如上方的螢幕截圖所示。

如要修正這個問題,請使用 StartEnd 術語,而非「左」和「右」。這項術語會根據目前語言的文字方向,適當設定文字的開頭和結尾,讓邊界和版面配置位於螢幕的正確區域。

  1. Open list_item.xml
  2. 將所有 LeftRight 參照替換為 StartEnd 參照。
app:layout_constraintStart_toStartOf="parent"

app:layout_constraintStart_toEndOf="@+id/gdg_image"
app:layout_constraintEnd_toEndOf="parent"
  1. ImageViewlayout_marginLeft 替換為 layout_marginStart。這樣一來,邊界就會移到正確位置,讓圖示遠離螢幕邊緣。
<ImageView
android:layout_marginStart="
?
  1. 開啟 fragment_gdg_list.xml。查看「Preview」窗格中的 GDG 清單。請注意,圖示仍指向錯誤方向,因為它是鏡像 (如果圖示未鏡像,請確認您仍從右至左預覽)。根據 Material Design 指南,圖示不應鏡像。
  2. 開啟「res/drawable/ic_gdg.xml」
  3. 在 XML 程式碼的第一行中,找出並刪除 android:autoMirrored="true",即可停用鏡像功能。
  4. 檢查「預覽」,或再次執行應用程式並開啟「Search GDG」畫面。版面配置現在應該已修正!

步驟 3:讓 Android Studio 為您代勞

在先前的練習中,您已採取初步措施來支援 RTL 語言。幸好,Android Studio 可以掃描應用程式,並為您設定許多基本項目。

  1. list_item.xmlTextView 中,將 layout_marginStart 改回 layout_marginLeft,讓掃描器有東西可尋找。
<TextView
android:layout_marginLeft="@dimen/spacing_normal"
  1. 在 Android Studio 中,依序選擇「Refactor」>「Add RTL support where possible」,然後勾選要更新資訊清單和版面配置檔案的方塊,以使用開始和結束屬性。

  1. 在「重構預覽」窗格中找到「app」資料夾,然後展開,直到所有詳細資料都開啟為止。
  2. 在應用程式資料夾下方,您會發現剛才變更的 layout_marginLeft 列為要重構的程式碼。

  1. 請注意,預覽畫面也會列出系統和程式庫檔案。在「layout」、「layout-watch-v20」和不屬於「app」的任何其他資料夾上按一下滑鼠右鍵,然後從內容選單中選擇「Exclude」

  1. 請立即進行重構。(如果系統檔案彈出視窗,請確認您已排除所有不屬於應用程式程式碼的資料夾)。
  1. 請注意,layout_marginLeft 已改回 layout_marginStart

步驟 3:探索語言代碼的資料夾

到目前為止,您只變更了應用程式使用的預設語言方向。如果是正式版應用程式,您會將 strings.xml 檔案傳送給翻譯人員,請他們翻譯成新語言。在本程式碼研究室中,應用程式會提供西班牙文的 strings.xml 檔案 (我們使用 Google 翻譯產生譯文,因此譯文不盡完美)。

  1. 在 Android Studio 中,將專案檢視畫面切換為「Project Files」
  2. 展開 res 資料夾,並注意 res/valuesres/values-es 的資料夾。資料夾名稱中的「es」是西班牙文的語言代碼。「values-"language code"」資料夾包含各支援語言的值。不含副檔名的「values」資料夾包含適用於其他情況的預設資源。

  1. values-es 中開啟 strings.xml,你會發現所有字串都是西班牙文。
  2. 在 Android Studio 中,開啟「Design」分頁中的 activity_main.xml
  3. 在「預覽地區設定」下拉式選單中選擇「西班牙文」。現在文字應該會顯示西班牙文。

  1. [選用] 如果您精通 RTL 語言,請建立 values 資料夾和該語言的 strings.xml,並在裝置上測試顯示效果。
  2. [選用] 變更裝置的語言設定,然後執行應用程式。請務必將裝置語言變更為自己看得懂的語言,否則要復原會有點困難!

在上一個工作中,您手動變更應用程式,然後使用 Android Studio 檢查是否有其他 RTL 改善項目。

無障礙功能檢查工具應用程式是您改善應用程式無障礙設計的最佳幫手。這項工具會掃描目標裝置上的應用程式,並提供改善建議,例如放大觸控目標、提高對比度,以及為圖片提供說明,讓應用程式更易於使用。無障礙功能掃描器由 Google 開發,可從 Play 商店安裝。

步驟 1:安裝並執行無障礙功能檢查工具

  1. 開啟 Play 商店,如有需要請登入帳戶。您可以在實體裝置或模擬器上執行這項操作。本程式碼研究室使用模擬器。
  1. 在 Play 商店中搜尋「Google LLC 的無障礙功能檢查工具」。請務必下載 Google 發行的正確應用程式,因為掃描作業需要許多權限!

  1. 在模擬器上安裝掃描器。
  2. 安裝完成後,按一下「開啟」
  3. 按一下「開始使用」
  4. 按一下「確定」,即可在「設定」中開始設定無障礙功能檢查工具。

  1. 按一下「無障礙功能檢查工具」,前往裝置的「無障礙設定」

  1. 按一下「使用服務」即可啟用。

  1. 按照畫面上的指示操作,並授予所有權限。
  2. 然後按一下「確定」,返回主畫面。畫面上可能會顯示藍色按鈕和勾號。按一下這個按鈕,即可觸發前景應用程式的測試。如要重新放置按鈕,請拖曳按鈕。這個按鈕會顯示在所有應用程式上方,因此你隨時可以觸發測試。

  1. 開啟或執行應用程式。
  2. 按一下藍色按鈕,並接受其他安全性警告和權限。

首次點選無障礙掃描器圖示時,應用程式會要求取得權限,以便擷取螢幕上顯示的所有內容。這項權限似乎非常可怕,事實也確實如此。

您幾乎不應授予這類權限,因為應用程式可藉此讀取您的電子郵件,甚至取得您的銀行帳戶資訊!不過,無障礙掃描器必須以使用者的方式檢查應用程式,才能正常運作,因此需要這項權限。

  1. 按一下藍色按鈕,然後等待分析完成。您會看到類似下圖的畫面,標題和 FAB 會以紅色方框標示。這表示這個畫面有兩項無障礙功能改善建議。

  1. 按一下 GDG Finder 周圍的方塊。這時會開啟含有額外資訊的窗格,如下所示,指出圖片對比度有問題。
  2. 展開「圖片對比」資訊,工具會建議補救措施。
  3. 按一下右側的箭頭,即可查看下一個項目的資訊。

  1. 在應用程式中,前往「Apply for GDG」畫面,並使用無障礙功能掃描工具掃描該畫面。如下圖左側所示,這會提供許多建議。確切來說是 12 個。公平地說,其中有些是類似商品的重複項目。
  2. 按一下底部工具列中的「堆疊」 圖示,即可查看所有建議清單,如下方右側螢幕截圖所示。您將在本程式碼研究室中解決所有這些問題。

Android 無障礙套件是 Google 推出的一系列應用程式,內含可讓應用程式更易於使用的工具。包括 TalkBack 等工具。TalkBack 螢幕閱讀器提供聽覺、觸覺和語音回饋,讓使用者不必看螢幕也能操作裝置及瀏覽內容。

結果發現,TalkBack 不僅適用於失明人士,許多視障人士也會使用這項功能。甚至只是想讓眼睛休息一下的人!

因此,無障礙功能適合所有人!在這項工作中,您將試用 TalkBack,並更新應用程式,確保應用程式能與 TalkBack 順暢運作。

步驟 1:安裝並執行無障礙套件

許多實體裝置都預先安裝了 TalkBack,但模擬器需要安裝這項功能。

  1. 開啟 Play 商店。
  2. 找出「無障礙套件」。請確認這是 Google 提供的正確應用程式。
  3. 如果尚未安裝,請安裝無障礙套件。
  4. 如要在裝置上啟用 TalkBack,請依序前往「設定」>「無障礙設定」,然後選取「使用服務」來開啟 TalkBack。與無障礙功能掃描器一樣,TalkBack 也需要權限才能讀取畫面內容。接受權限要求後,TalkBack 會顯示教學課程清單,協助你瞭解如何有效使用 TalkBack。
  5. 建議您先暫停,並完成教學課程,至少要學會如何關閉 TalkBack。
  6. 如要離開教學課程,請按一下返回按鈕選取,然後輕觸兩下畫面上的任何位置。
  1. 使用 TalkBack 探索 GDG Finder 應用程式。注意 TalkBack 未提供實用螢幕或控制項資訊的位置。您將在下一個練習中修正這個問題。

步驟 2:新增內容說明

內容描述元是說明觀看次數意義的描述性標籤。大部分檢視區塊都應提供內容說明。

  1. 執行 GDG Finder 應用程式並啟用 TalkBack,然後前往「Apply to run GDG」(申請執行 GDG) 畫面。
  2. 輕觸主要圖片,但沒有任何反應。
  3. 開啟 add_gdg_fragment.xml
  4. ImageView 中,新增內容描述元屬性,如下所示。stage_image_description 字串已在 strings.xml 中提供。
android:contentDescription="@string/stage_image_description"
  1. 執行應用程式。
  2. 前往「Apply to run GDG」,然後點選圖片。現在應該會聽到圖片的簡短說明。
  3. [選用] 為這個應用程式中的其他圖片新增內容說明。在正式版應用程式中,所有圖片都必須有內容說明。

步驟 3:在可編輯的文字欄位中新增提示

如果是可編輯的元素 (例如 EditText),您可以在 XML 中使用 android:hint,協助使用者瞭解要輸入的內容。提示一律會顯示在 UI 中,因為這是輸入欄位的預設文字。

  1. 仍在 add_gdg_fragment.xml 中。
  2. 請參考下方程式碼,新增內容說明和提示。

新增至「textViewIntro」:

android:contentDescription="@string/add_gdg"

分別新增至編輯文字:

android:hint="@string/your_name_label"

android:hint="@string/email_label"

android:hint="@string/city_label"

android:hint="@string/country_label"

android:hint="@string/region_label"
  1. 為「labelTextWhy」新增內容說明。
android:contentDescription="@string/motivation" 
  1. EditTextWhy 中新增提示。標記編輯方塊後,請在標籤中加入內容說明,並在方塊中加入提示。
android:hint="@string/enter_motivation"
  1. 為提交按鈕新增內容說明。所有按鈕都必須說明按下後會發生什麼事。
android:contentDescription="@string/submit_button_description"
  1. 啟用 TalkBack 執行應用程式,然後填寫表單,申請經營 GDG。

步驟 4:建立內容群組

如要讓 TalkBack 將 UI 控制項視為群組,可以使用內容分組。系統會將相關內容歸類為一組,並一起朗讀。輔助技術使用者不必再頻繁滑動、掃描或等待,就能探索畫面上的所有資訊。這不會影響控制項在螢幕上的顯示方式。

如要將 UI 元件分組,請將這些元件包裝到 ViewGroup 中,例如 LinearLayout。在 GDG Finder 應用程式中,labelTextWhyeditTextWhy 元素在語意上屬於同一組,因此非常適合分組。

  1. 開啟 add_gdg_fragment.xml
  2. LabelTextWhyEditTextWhy 周圍加上 LinearLayout,即可建立內容群組。複製並貼上下列程式碼。這個 LinearLayout 已經包含您需要的部分樣式。(請確認 button 位於 LinearLayout 之外)。
<LinearLayout android:id="@+id/contentGroup" android:layout_width="match_parent"
            android:layout_height="wrap_content" android:focusable="true"
            app:layout_constraintTop_toBottomOf="@id/EditTextRegion"
            android:orientation="vertical" app:layout_constraintStart_toStartOf="@+id/EditTextRegion"
            app:layout_constraintEnd_toEndOf="@+id/EditTextRegion"
            android:layout_marginTop="16dp" app:layout_constraintBottom_toTopOf="@+id/button"
            android:layout_marginBottom="8dp">

     <!-- label and edit text here –>

<LinearLayout/>
  1. 依序選擇「Code」>「Reformat code」,正確縮排所有程式碼。
  2. labelTextWhyeditTextWhy 移除所有版面配置邊界。
  3. labelTextWhy 中,將 layout_constraintTop_toTopOf 限制變更為 contentGroup
app:layout_constraintTop_toTopOf="@+id/contentGroup" />
  1. editTextWhy 中,將 layout_constraintBottom_toBottomOf 限制變更為 contentGroup
app:layout_constraintBottom_toBottomOf="@+id/contentGroup"
  1. EditTextRegionButton 限制在 contentGroup 內,即可修正錯誤。
app:layout_constraintBottom_toTopOf="@+id/contentGroup"
  1. LinearLayout 中新增邊界。您可以選擇將這個邊界做為維度擷取。
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"

如需協助,請對照解決方案程式碼中的 add_gdg_fragment.xml 檢查程式碼。

  1. 執行應用程式,並使用 TalkBack 探索「Apply to run GDG」(申請經營 GDG) 畫面。

步驟 5:新增即時區域

目前提交按鈕上的標籤為「確定」。如果按鈕在表單提交前有一個標籤和說明,使用者點選並提交表單後,動態變更為不同的標籤和內容說明,這樣會比較好。您可以使用即時區域執行這項操作。

無障礙服務會根據即時區域,判斷是否要在檢視區塊變更時通知使用者。舉例來說,告知使用者密碼有誤或發生網路錯誤,是提升應用程式無障礙程度的好方法。在本範例中,為求簡單,您會在提交按鈕變更狀態時通知使用者。

  1. 開啟 add_gdg_fragment.xml
  2. 使用提供的 submit 字串資源,將按鈕的文字指派變更為「提交」
android:text="@string/submit"
  1. 設定 android:accessibilityLiveRegion 屬性,將即時區域新增至按鈕。輸入時,系統會提供多種值選項。視變更的重要性而定,您可以選擇是否要中斷使用者操作。如果值為「assertive」,無障礙服務會中斷正在進行的語音播報,立即宣布這個檢視區塊的變更。如果將值設為「none」,系統就不會發布任何變更。設為「禮貌」時,無障礙服務會宣布變更,但會等待輪到自己。將值設為「polite」。

android:accessibilityLiveRegion="polite"
  1. add 套件中,開啟 AddGdgFragment.kt
  2. showSnackBarEvent Observer 中顯示 SnackBar 後,請為按鈕設定新的內容說明和文字。
binding.button.contentDescription=getString(R.string.submitted)
binding.button.text=getString(R.string.done)
  1. 執行應用程式,然後按一下按鈕。很抱歉,按鈕和字型太小了!

步驟 6:修正按鈕樣式

  1. add_gdg_fragment.xml 中,將按鈕的 widthheight 變更為 wrap_content,這樣就能顯示完整標籤,按鈕大小也適中。
android:layout_width="wrap_content"
android:layout_height="wrap_content"
  1. 從按鈕中刪除 backgroundTinttextColortextSize 屬性,讓應用程式使用更完善的主題樣式。
  2. textViewIntro 刪除 textColor 屬性。主題顏色應提供良好的對比度。
  3. 執行應用程式。您會發現「Submit」按鈕變得更好用了。點選「提交」,注意按鈕會變成「完成」

方塊是代表屬性、文字、實體或動作的精簡元素。使用者可以輸入資訊、選取選項、篩選內容或觸發動作。

Chip 小工具是 ChipDrawable 周圍的細檢視區塊包裝函式,內含所有版面配置和繪圖邏輯。額外邏輯可支援觸控、滑鼠、鍵盤和無障礙瀏覽功能。主要晶片和關閉圖示會視為個別的邏輯子檢視區塊,並包含各自的導覽行為和狀態。

方塊會使用可繪項目。Android 可繪項目可讓您在畫面上繪製圖片、形狀和動畫,且可為固定大小或動態大小。您可以將圖片當做可繪項目使用,例如 GDG 應用程式中的圖片。此外,您也可以使用向量繪圖,繪製任何想像得到的內容。此外,還有可調整大小的可繪項目,稱為 9 格可繪項目,本程式碼研究室不會介紹這項內容。drawable/ic_gdg.xml 中的 GDG 標誌是另一個可繪項目。

可繪項目不是檢視區塊,因此無法直接放在 ConstraintLayout 內,必須放在 ImageView 內。您也可以使用可繪項目為文字檢視區塊或按鈕提供背景,而背景會繪製在文字後方。

步驟 1:將晶片新增至 GDG 清單

下方勾選的晶片使用三個可繪項目。背景和勾號都是可繪製物件。輕觸晶片會產生漣漪效果,這是透過特殊的 RippleDrawable 達成,可顯示因應狀態變更的漣漪效果。

在這項工作中,您會將動態磚新增至 GDG 清單,並在選取動態磚時變更其狀態。在本練習中,您要在「Search」畫面的頂端新增一列稱為「晶片」的按鈕。每個按鈕都會篩選 GDG 清單,讓使用者只收到所選地區的結果。選取按鈕後,按鈕會變更背景並顯示勾號。

  1. 開啟 fragment_gdg_list.xml
  2. HorizontalScrollView. 內建立 com.google.android.material.chip.ChipGroup,並將其 singleLine 屬性設為 true,讓所有晶片都排列在可水平捲動的同一行。將 singleSelection 屬性設為 true,這樣一次只能選取群組中的一個晶片。程式碼如下。
<com.google.android.material.chip.ChipGroup
    android:id="@+id/region_list"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:singleSelection="true"
    android:padding="@dimen/spacing_normal"/>
  1. layout 資料夾中,建立名為 region.xml 的新版面配置資源檔案,用於定義單一 Chip 的版面配置。
  2. 在 region.xml 中,將所有程式碼替換為下列其中一個 Chip 的版面配置。請注意,這個 Chip 是 Material 元件。另請注意,您是透過設定 app:checkedIconVisible 屬性取得勾號。系統會顯示缺少 selected_highlight 顏色的錯誤訊息。
<?xml version="1.0" encoding="utf-8"?>

<com.google.android.material.chip.Chip
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Widget.MaterialComponents.Chip.Choice"
        app:chipBackgroundColor="@color/selected_highlight"
        app:checkedIconVisible="true"
        tools:checked="true"/>
  1. 如要建立缺少的 selected_highlight 顏色,請將游標放在 selected_highlight 上,叫出意圖選單,然後為所選醒目顯示項目建立顏色資源。預設選項沒有問題,請按一下「OK」。系統會在 res/color 資料夾中建立檔案。
  2. 開啟「res/color/selected_highlight.xml」。在這個以 <selector> 編碼的顏色狀態清單中,您可以為不同狀態提供不同顏色。每個狀態和相關聯的顏色都會編碼為 <item>。如要進一步瞭解這些顏色,請參閱「顏色主題」。
  1. <selector> 內,將預設顏色 colorOnSurface 的項目新增至狀態清單。在州別清單中,請務必涵蓋所有州別。其中一種做法是設定預設顏色。
<item android:alpha="0.18" android:color="?attr/colorOnSurface"/>
  1. 在預設顏色上方,新增 item,並將顏色設為 colorPrimaryVariant,然後限制只有在所選狀態為 true 時才能使用。系統會從上到下處理狀態清單,就像處理 case 陳述式一樣。如果沒有符合的狀態,系統會套用預設狀態。
<item android:color="?attr/colorPrimaryVariant"
         android:state_selected="true" />

步驟 2:顯示晶片列

GDG 應用程式會建立晶片清單,顯示有 GDG 的區域。選取晶片後,應用程式會篩選結果,只顯示該區域的 GDG 結果。

  1. search 套件中,開啟 GdgListFragment.kt
  2. onCreateView() 中,於 return 陳述式正上方,為 viewModel.regionList 新增觀察器,並覆寫 onChanged()。當檢視畫面模型提供的區域清單變更時,需要重新建立晶片。新增陳述式,在提供的 datanull 時立即傳回。
viewModel.regionList.observe(viewLifecycleOwner, object: Observer<List<String>> {
        override fun onChanged(data: List<String>?) {
             data ?: return
        }
})
  1. onChanged() 內,於空值測試下方,將 binding.regionList 指派給名為 chipGroup 的新變數,以快取 regionList
val chipGroup = binding.regionList
  1. 在下方建立新的 layoutInflator,用於從 chipGroup.context 膨脹晶片。
val inflator = LayoutInflater.from(chipGroup.context)
  1. 清除並重新建構專案,即可解決資料繫結錯誤。

現在您可以在膨脹器下方建立實際的晶片,regionList 中的每個區域各有一個晶片。

  1. 建立變數 children,用來保存所有方塊。在傳入的 data 中指派對應函式,建立並傳回每個晶片。
val children = data.map {} 
  1. 在對應 lambda 中,為每個 regionName 建立並擴充方塊。完成的程式碼如下。
val children = data.map {
   val children = data.map { regionName ->
       val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
       chip.text = regionName
       chip.tag = regionName
       // TODO: Click listener goes here.
       chip
   }
}
  1. 在 lambda 中,就在傳回 chip 之前,新增點按事件監聽器。點選 chip 時,請將其狀態設為 checked。在 viewModel 中呼叫 onFilterChanged(),這會觸發一連串事件,擷取這個篩選條件的結果。
chip.setOnCheckedChangeListener { button, isChecked ->
   viewModel.onFilterChanged(button.tag as String, isChecked)
}
  1. 在 lambda 結尾,從 chipGroup 移除所有目前的檢視區塊,然後將 children 中的所有方塊新增至 chipGroup。(您無法更新晶片,因此必須移除並重新建立 chipGroup 的內容)。
chipGroup.removeAllViews()

for (chip in children) {
   chipGroup.addView(chip)
}

完成的觀察器應如下所示:

   override fun onChanged(data: List<String>?) {
       data ?: return

       val chipGroup = binding.regionList
       val inflator = LayoutInflater.from(chipGroup.context)

       val children = data.map { regionName ->
           val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
           chip.text = regionName
           chip.tag = regionName
           chip.setOnCheckedChangeListener { button, isChecked ->
               viewModel.onFilterChanged(button.tag as String, isChecked)
           }
           chip
       }
       chipGroup.removeAllViews()

       for (chip in children) {
           chipGroup.addView(chip)
       }
   }
})
  1. 執行應用程式並搜尋 GDGS,開啟「搜尋」畫面,即可使用新晶片。點選每個方塊後,應用程式會在下方顯示篩選器群組。

如果裝置設定為啟用夜間模式,應用程式就能透過夜間模式將顏色變更為深色主題。在夜間模式下,應用程式會將預設的淺色背景變更為深色,並相應變更所有其他螢幕元素。

步驟 1:啟用夜間模式

如要為應用程式提供深色主題,請將主題從 Light 主題變更為名為 DayNight 的主題。DayNight 主題會根據模式顯示為淺色或深色。

  1. styles.xml, 中,將 AppTheme 父項主題從 Light 變更為 DayNight
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
  1. MainActivityonCreate() 方法中,呼叫 AppCompatDelegate.setDefaultNightMode() 即可透過程式輔助開啟深色主題。
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
  1. 執行應用程式,確認應用程式已切換為深色主題。

步驟 2:產生專屬的深色主題調色盤

如要自訂深色主題,請建立資料夾,並使用 -night 限定符,供深色主題使用。舉例來說,您可以建立名為 values-night 的資料夾,在夜間模式中顯示特定顏色。

  1. 前往 material.io 顏色挑選器工具,建立夜間主題調色盤。例如,您可以根據深藍色建立主題。
  2. 產生並下載 colors.xml 檔案。
  3. 切換至「Project Files」檢視畫面,列出專案中的所有資料夾。
  4. 找出並展開 res 資料夾。
  5. 建立 res/values-night 資源資料夾。
  6. 將新的 colors.xml 檔案新增至 res/values-night 資源資料夾。
  7. 執行應用程式 (仍啟用夜間模式),應用程式應會使用您為 res/values-night 定義的新顏色。請注意,方塊會使用新的次要顏色。

Android Studio 專案:GDGFinderFinal

支援 RTL 語言

  • 在 Android 資訊清單中,設定 android:supportsRtl="true"
  • 您可以在模擬器中預覽 RTL,並使用自己的語言檢查畫面版面配置。在裝置或模擬器上開啟「設定」,然後在「開發人員選項」中選取「強制使用從右至左版面配置」
  • LeftRight 的參照替換為 StartEnd 的參照。
  • 刪除 android:autoMirrored="true" 即可停用可繪項目的鏡像功能。
  • 選擇「Refactor」>「Add RTL support where possible」 ,讓 Android Studio 為您完成這項工作。
  • 使用 values-"語言代碼" 資料夾儲存語言專屬資源。

掃描無障礙功能

採用 TalkBack 適用的設計,並提供內容說明

  • 安裝 Google 提供的 Android 無障礙套件,其中包含 TalkBack。
  • 為所有 UI 元素新增內容說明。例如:
    android:contentDescription="@string/stage_image_description"
  • 如果是可編輯的元素 (例如 EditText),請在 XML 中使用 android:hint 屬性,向使用者提供輸入提示。
  • 將相關元素包裝成檢視畫面群組,即可建立內容群組。
  • 建立即時區域,透過 android:accessibilityLiveRegion 為使用者提供額外意見回饋。

使用方塊實作篩選器

  • 方塊是代表屬性、文字、實體或動作的精簡元素。
  • 如要建立一組動態磚,請使用 com.google.android.material.chip.ChipGroup
  • 定義一個 com.google.android.material.chip.Chip 的版面配置。
  • 如要讓晶片變更顏色,請提供顏色狀態清單做為 <selector>,並使用有狀態的顏色:
    <item android:color="?attr/colorPrimaryVariant"
    android:state_selected="true" />
  • 在檢視區塊模型中新增資料的觀察者,將方塊繫結至即時資料。
  • 如要顯示方塊,請為方塊群組建立膨脹器:
    LayoutInflater.from(chipGroup.context)
  • 建立晶片、新增會觸發所需動作的點擊事件監聽器,然後將晶片新增至晶片群組。

支援深色模式

  • 使用 DayNight AppTheme 支援深色模式。
  • 您可以透過程式輔助方式設定深色模式:
    AppCompatDelegate.setDefaultNightMode()
  • 建立 res/values-night 資源資料夾,為深色模式提供自訂顏色和值。

Android 開發人員說明文件:

其他資源:

本節列出的作業可由課程講師指派給學習本程式碼研究室的學員。講師可自由採取以下行動:

  • 視需要指派作業。
  • 告知學員如何繳交作業。
  • 為作業評分。

講師可以視需求使用全部或部分建議內容,也可以自由指派任何其他合適的作業。

如果您是自行學習本程式碼研究室,不妨利用這些作業驗收學習成果。

第 1 題

如要支援 RTL 語言,下列哪項是必要條件?

▢ 將屬性中的 LeftRight 替換為 StartEnd

▢ 切換為 RTL 語言

▢ 確認所有圖示都使用 android:autoMirrored="true"

▢ 提供內容說明

第 2 題

大多數 Android 裝置內建下列哪些無障礙工具?

▢ TalkBack

▢ 無障礙功能檢查工具

▢ 在 Android Studio 中,依序選取「Refactor」>「Add RTL support where possible」

▢ Lint

第 3 題

下列有關動態磚的敘述何者不正確?

▢ 將晶片顯示為 ChipGroup 的一部分。

▢ 您可以為 ChipGroup 提供顏色狀態清單。

▢ 方塊是代表輸入內容、屬性或動作的精簡元素。

▢ 如果應用程式使用動態磚,請務必啟用 DarkTheme

第 4 題

哪項主題可提供深色和淺色模式的樣式?

DayNight

DarkTheme

DarkAndLightTheme

Light

第 5 題

什麼是即時區域?

▢ 包含使用者重要資訊的節點

▢ 螢幕上的區域,會根據 Material 指南變更形狀

▢ 允許串流播放影片的檢視畫面

▢ 可繪項目動畫