處理不同的手錶形狀

Wear OS 中的應用程式使用的版面配置技巧與其他 Android 裝置相同,但必須根據特定手錶的限制來設計。

注意:請勿將整個功能和 UI 從行動應用程式轉移至 Wear OS,這麼做無法帶來良好的使用者體驗。

如果您是針對方形手錶設計應用程式,則圓形手錶上螢幕角落的內容可能會遭到裁切。如果您使用可捲動的垂直清單,那麼受到的影響可能會較小,因為使用者能夠捲動畫面將內容置中。不過,如果是單螢幕畫面,可能會導致使用者體驗不佳。

圖 1 顯示一個版面配置在正方形和圓形螢幕上顯示的外觀:

圖 1. 專為正方形螢幕設計的版面配置在圓形螢幕上可能無法正確顯示。

如果您為版面配置使用下列設定,文字會在圓形螢幕的裝置上會無法正確顯示:

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:text="@string/very_long_hello_world"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

解決問題的方法有兩種,詳情請見後續章節:

  • 對正方形和圓形裝置一併使用 Wear OS UI 程式庫中的版面配置。
    • 您可以使用 BoxInsetLayout,根據裝置螢幕形狀套用不同的視窗插邊。如果您想在這兩種螢幕形狀上使用類似的版面配置,但不想裁切到圓形螢幕接近邊緣的畫面,請使用這個方法。
    • 如果您想要顯示並操控針對圓形螢幕進行最佳化的項目垂直清單,可以使用 WearableRecyclerView 建立曲線版面配置。
  • 按照提供替代資源指南所述,為正方形和圓形裝置提供替代版面配置資源。在執行階段,Wear OS 會偵測裝置螢幕的形狀,並載入正確的版面配置。

如要進一步瞭解如何設計應用程式,請參閱「Wear OS 設計指南」。

使用 BoxInsetLayout

圖 2. 圓形螢幕上的視窗插邊。

Wear OS UI 程式庫中的 BoxInsetLayout 類別可讓您定義同時適用於正方形和圓形螢幕的單一版面配置。這個類別會根據螢幕形狀套用必要的視窗插邊,方便您以檢視畫面的中央或畫面邊緣對齊。

圖 2 中的灰色正方形會顯示 BoxInsetLayout 在套用必要視窗插邊後,將子檢視畫面自動顯示在圓形螢幕上的畫面。如要在這個區域中顯示,子檢視畫面會使用下列值指定 layout_boxedEdges 屬性:

  • topbottomleftright 的結合。例如,"left|top" 值會將子項的左側和頂端邊緣置於圖 2 的灰色正方形中。
  • "all" 值會將子項中的所有內容置於圖 2 的灰色正方形中。這是最常見的 ConstraintLayout 方法。

正方形螢幕的視窗插邊為 0,因此系統會忽略 layout_boxedEdges 屬性。

圖 3:同時適用於正方形和圓形螢幕的版面配置定義。

圖 3 所示的版面配置使用 <BoxInsetLayout> 元素,並適用於正方形和圓形螢幕:

<androidx.wear.widget.BoxInsetLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:padding="15dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="5dp"
        app:layout_boxedEdges="all">

        <TextView
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:text="@string/sometext"
            android:textAlignment="center"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageButton
            android:background="@android:color/transparent"
            android:layout_height="50dp"
            android:layout_width="50dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:src="@drawable/cancel" />

        <ImageButton
            android:background="@android:color/transparent"
            android:layout_height="50dp"
            android:layout_width="50dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:src="@drawable/ok" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.wear.widget.BoxInsetLayout>

請注意,版面配置的部分會以粗體標示:

  • android:padding="15dp"

    此行會將邊框間距指派給 <BoxInsetLayout> 元素。

  • android:padding="5dp"

    此行會將邊框間距指派給內部 ConstraintLayout 元素。

  • app:layout_boxedEdges="all"

    此行可確保 ConstraintLayout 元素及其子項在圓形螢幕上的視窗插邊定義區域內。此線條在正方形螢幕不會影響。

使用曲線版面配置

您可以透過 Wear OS UI 程式庫中的 WearableRecyclerView 類別,選擇採用針對圓形螢幕進行最佳化調整的曲線版面配置。如要為應用程式中的可捲動清單啟用曲線版面配置,請參閱「在 Wear OS 上建立清單」。

針對正方形和圓形螢幕使用不同的版面配置

另一個同時支援正方形和圓形螢幕的方法,是為不同的螢幕形狀提供替代資源。針對版面配置、維度或其他資源類型,將資源限定詞設為 roundnotround

例如,您可以考慮採用以下方式安排版面配置:

  • 針對適用於圓形與正方形手錶的版面配置,使用 layout/ 目錄。
  • 針對適用於特定螢幕形狀的版面配置,使用 layout-round/layout-notround/ 目錄。

您也可以使用 res/valuesres/values-roundres/values-notround 資源目錄。以這種方式整理資源,可以共用一個版面配置,只須根據裝置類型變更某些特定屬性。

改變值

為圓形和方形手錶設計版面配置的其中一種方法是使用 values/dimens.xmlvalues-round/dimens.xml。您可以透過指定不同的邊框間距設定,使用單一 layout.xml 檔案和兩個 dimens.xml 檔案建立以下版面配置:

<dimen name="header_start_padding">36dp</dimen>
<dimen name="header_end_padding">22dp</dimen>
<dimen name="list_start_padding">36dp</dimen>
<dimen name="list_end_padding">22dp</dimen>
使用 values-round/dimens.xml

圖 4. 使用values-round/dimens.xml

<dimen name="header_start_padding">16dp</dimen>
<dimen name="header_end_padding">16dp</dimen>
<dimen name="list_start_padding">10dp</dimen>
<dimen name="list_end_padding">10dp</dimen>
使用 values/dimens.xml

圖 5. 使用 values/dimens.xml

嘗試不同值,看看哪個值成效最佳。

使用 XML 填補下巴

某些手錶圓形螢幕上會有插邊 (也稱為「下巴」)。如果不填補下巴,部分設計可能會遭到遮擋。

舉例來說,假設您採用以下設計:

基本的心形設計

圖 6. 基本的心形設計。

這個 activity_main.xml 程式碼片段定義了其版面配置。

<FrameLayout
  ...
  <androidx.wear.widget.RoundedDrawable
    android:id="@+id/androidbtn"
    android:src="@drawable/ic_android"
    .../>
   <ImageButton
    android:id="@+id/lovebtn"
    android:src="@drawable/ic_favorite"
    android:paddingTop="5dp"
    android:paddingBottom="5dp"
    android:layout_gravity="bottom"
    .../>
</FrameLayout>

如果未採取任何動作,部分設計會遭下巴擋住。

基本的心形設計

圖 7. 未套用修正。

您可以使用 fitsSystemWindows 屬性設定邊框間距,以避免 chin。下列 activity_main.xml 程式碼片段顯示使用 fitsSystemWindows

<ImageButton
  android:id="@+id/lovebtn"
  android:src="@drawable/ic_favorite"
  android:paddingTop="5dp"
  android:paddingBottom="5dp"
  android:fitsSystemWindows="true"
  .../>
使用 fitsSystemWindows

圖 8. 使用 fitsSystemWindows 屬性。

現在系統會覆寫您定義的頂端和底部邊框間距值,讓所有項目都能納入系統視窗中。如要修正這個問題,請使用 InsetDrawable 取代邊框間距值。

建立 inset_favorite.xml 檔案來定義邊框間距值:

<inset
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:drawable="@drawable/ic_favorite"
  android:insetTop="5dp"
  android:insetBottom="5dp" />

移除 activity_main.xml 檔案中的邊框間距:

<ImageButton
  android:id="@+id/lovebtn"
  android:src="@drawable/inset_favorite"
  android:paddingTop="5dp"
  android:paddingBottom="5dp"
  android:fitsSystemWindows="true"
  .../>
使用 InsetDrawables

圖 9. 使用 InsetDrawable

透過程式輔助管理 chin

如果您需要使用 XML 以宣告式方式進行更多控制,可以以程式化方式調整版面配置。如要取得下巴的大小,請將 View.OnApplyWindowInsetsListener 附加至版面配置最外層的檢視畫面。

請將以下內容新增到 activity_main.xml 檔案中:

Kotlin

private var chinSize: Int = 0

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    // Find the outermost element
    findViewById<View>(R.id.outer_container).apply {
        // Attach a View.OnApplyWindowInsetsListener
        setOnApplyWindowInsetsListener { v, insets ->
            chinSize = insets.systemWindowInsetBottom
            // The following line is important for inner elements that react to insets
            v.onApplyWindowInsets(insets)
            insets
        }
    }
}

Java

private int chinSize;
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // Find the outermost element
    final View container = findViewById(R.id.outer_container);
    // Attach a View.OnApplyWindowInsetsListener
    container.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
        @Override
        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
            chinSize = insets.getSystemWindowInsetBottom();
            // The following line is important for inner elements that react to insets
            v.onApplyWindowInsets(insets);
            return insets;
        }
    });
}