Anroid Wear OS 手錶應用開發 - UI

NanBox發表於2019-03-02

Wear UI

智慧手錶相對手機來說,由於使用場景不同,且螢幕較小,所以應用的設計、互動和手機是有些區別的。相對來說,佈局會更簡潔,更多地使用滑動手勢進行操作。

為此,在 Wear OS 上,官方提供了一系列新的控制元件和互動,通過它們,我們可以很方便地打造出一個適合手錶互動的應用。

新增依賴

下面用到的控制元件都來自 Wear 控制元件庫,需要在 build.gradle 檔案中新增以下依賴:

implementation 'com.android.support:wear:28.0.0'
複製程式碼

佈局

常見的錶盤有方形和圓形兩種,使用普通佈局的情況下,可能會出現這種情況:

Anroid Wear OS 手錶應用開發 - UI

為了使圓形錶盤上的內容不超出邊界,同時相容方形錶盤,我們可以使用 BoxInsetLayout 這個佈局:

<android.support.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">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:boxedEdges="all">
        
        <...>
        
    </FrameLayout>
    
</android.support.wear.widget.BoxInsetLayout>
複製程式碼

這樣可以在保證方形錶盤不受影響的情況下,圓形佈局的內容,不會超過顯示邊界:

Anroid Wear OS 手錶應用開發 - UI

導航抽屜欄

為了節省寶貴的顯示空間,通常手錶應用是沒有標題欄的,在使用 ViewPager 的時候,也沒有 TabLayout 的顯示,但因此我們無法很好的確認當前頁面。

導航欄 WearableNavigationDrawerView 就是用來解決這個問題的,我們先看看它的效果:

Anroid Wear OS 手錶應用開發 - UI

從手錶頂部向下滑,會出現一個導航欄,顯示當前頁面的圖示和標題。當存在多個頁面時,通過左右滑動它來切換頁面。

下面來看看它的用法,我們修改佈局檔案,使用 WearableDrawerLayout 作為根佈局,新增導航欄控制元件:

<android.support.wear.widget.drawer.WearableNavigationDrawerView
        android:id="@+id/navigation_drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:navigationStyle="multiPage"/>
複製程式碼

當存在多個頁面時,需要新增 app:navigationStyle="multiPage" 這個屬性。

和 ViewPager 類似,我們需要給它設定一個介面卡,設定每個頁面的圖示和標題,像這樣:

class MainDrawerAdapter(context: Context) :
    WearableNavigationDrawerView.WearableNavigationDrawerAdapter() {

    private val mContext = context

    override fun getItemText(pos: Int): CharSequence {
        return when (pos) {
            0 -> "第一頁"
            else -> "第二頁"
        }
    }

    override fun getItemDrawable(pos: Int): Drawable {
        return when (pos) {
            0 -> ContextCompat.getDrawable(mContext, R.drawable.icon_one)!!
            else -> ContextCompat.getDrawable(mContext, R.drawable.icon_two)!!
        }
    }

    override fun getCount(): Int {
        return 2
    }

}
複製程式碼

然後在 Activity 中設定:

navigation_drawer.setAdapter(MainDrawerAdapter(this))
navigation_drawer.controller.peekDrawer()
navigation_drawer.addOnItemSelectedListener { pos ->
    // TODO 切換頁面
}
複製程式碼

這裡面的 controller.peekDrawer() 是讓導航欄在頂部露出一小部分,提示使用者這裡是有東西可以下滑的,也可以呼叫 controller.closeDrawer() 完全隱藏導航欄。

操作抽屜欄

當需要對當前頁面進行一些操作的時候,但頁面裡又沒有空間再放按鈕了怎麼辦?既然可以從頂部下拉出導航欄,要不在底部上拉出一個操作欄?操作欄 WearableActionDrawerView 就是用來做這個的。

通過給操作欄設定 menu 檔案,它會以列表的形式展示可操作項,佈局中這麼寫:

<android.support.wear.widget.drawer.WearableActionDrawerView
    android:id="@+id/action_drawer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:actionMenu="@menu/action_drawer_menu"/>
複製程式碼

程式碼中使用:

action_drawer.controller.peekDrawer()
action_drawer.setOnMenuItemClickListener { item -> 
    // TODO 點選選單
    true
}
複製程式碼

和頂部導航欄類似,controller.peekDrawer() 會在底部露出一小部分操作欄,如果當前頁面是一個列表,這一部分會在列表滑動時隱藏,在列表到頂部和底部時顯示:

Anroid Wear OS 手錶應用開發 - UI

露出部分預設會顯示操作欄第一項的圖示,可以在佈局中新增 app:showOverflowInPeek="true",讓它顯示豎直三個點的省略圖示。

自定義抽屜欄

導航欄 WearableNavigationDrawerView 和 操作欄 WearableActionDrawerView 用起來很簡單,但是它們的樣式是固定的,一個只能顯示圖示加標題,一個只能顯示 menu 格式的列表。

這兩個控制元件都繼承自 WearableDrawerView,所以兩者都可以通過 WearableDrawerView 來實現自定義樣式。下面是一個簡單的自定義底部抽屜欄佈局:

<android.support.wear.widget.drawer.WearableDrawerView
        android:id="@+id/action_drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="bottom"
        app:drawerContent="@+id/drawer_content"
        app:peekView="@+id/peek_view">

    <FrameLayout
            android:id="@+id/drawer_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

        <include layout="@layout/layout_bottom_drawer"/>

    </FrameLayout>

    <FrameLayout
            android:id="@+id/peek_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:paddingTop="8dp"
            android:paddingBottom="8dp"
            android:orientation="horizontal">

        <ImageView
                android:layout_width="16dp"
                android:layout_height="16dp"
                android:src="@drawable/icon_omit"
                tools:ignore="ContentDescription"/>

    </FrameLayout>

</android.support.wear.widget.drawer.WearableDrawerView>
複製程式碼

通過 layout_gravity 來設定抽屜欄是在頂部還是底部。它包裹了抽屜欄的主檢視 drawer_content 和關閉時露出部分的檢視 peek_view。這樣我們就可以在 layout_bottom_drawer 中設定自己想要的佈局了,其他用法都和上面是一樣的。

確認動畫

當處理完某個業務之後,我們通常需要給使用者一個處理成功或失敗的提示,在 Wear OS 上,我們可以用一個 Activity 來展示確認動畫。

ConfirmationActivity 是官方提供的用來展示確認動畫的 Activity。

Anroid Wear OS 手錶應用開發 - UI

用起來也很簡單,先在 manifest 檔案中註冊:

<manifest>
  <application>
    ...
    <activity
        android:name="android.support.wearable.activity.ConfirmationActivity">
    </activity>
  </application>
</manifest>
複製程式碼

需要顯示確認的時候,通過傳參跳轉就好了:

val intent = Intent(this, ConfirmationActivity::class.java)
intent.putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE, ConfirmationActivity.SUCCESS_ANIMATION)
intent.putExtra(ConfirmationActivity.EXTRA_MESSAGE, message)
startActivity(intent)
複製程式碼

這裡面,EXTRA_ANIMATION_TYPE 是動畫型別,它有以下三個可選項:

  • SUCCESS_ANIMATION
  • FAILURE_ANIMATION
  • OPEN_ON_PHONE_ANIMATION

EXTRA_MESSAGE 則是要顯示的文字內容。

環形進度條

CircularProgressLayout 是一個環形的進度條,通常用它包裹一個圓形按鈕:

Anroid Wear OS 手錶應用開發 - UI

可以用它來做防誤觸,使用者點選按鈕後,允許在進度條走完之前,點選取消操作。

我們把它新增到佈局中:

<android.support.wear.widget.CircularProgressLayout
    android:id="@+id/circular_progress"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="4dp"
    app:backgroundColor="@color/darkblue"
    app:colorSchemeColors="@color/lightblue"
    app:strokeWidth="4dp">
    
    <ImageView
      android:id="@+id/image_view"
      android:src="@drawable/cancel"
      android:layout_width="40dp"
      android:layout_height="40dp" />
      
</android.support.wear.widget.CircularProgressLayout>
複製程式碼

對 CircularProgressLayout 的監聽和操作如下:

// 監聽進度
circular_progress.setOnTimerFinishedListener {
    // TODO 進度完成
}
// 設定進度總時間
circular_progress.totalTime = 1000
// 開始計時
circular_progress.startTimer()
// 結束計時
circular_progress.stopTimer()
複製程式碼

列表

如果對比方形錶盤和圓形錶盤的手錶,他們的應用列表介面是這樣的:

Anroid Wear OS 手錶應用開發 - UI

Anroid Wear OS 手錶應用開發 - UI

在圓形錶盤上,列表是沿著錶盤左邊,曲線排列滾動的。這就是列表控制元件 WearableRecyclerView 實現的效果。

WearableRecyclerView 繼承自 RecyclerView,所以基本用法都是一樣的。

在佈局中加入:

<android.support.wear.widget.WearableRecyclerView
    android:id="@+id/wearable_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />
複製程式碼

程式碼中設定:

// 使列表上的第一項和最後一個項在螢幕上垂直居中對齊
wearable_recycler_view.isEdgeItemsCenteringEnabled = true
// 使用 WearableLinearLayoutManager 管理佈局
wearable_recycler_view.layoutManager = WearableLinearLayoutManager(this)
複製程式碼

如果想自定義別的滾動效果,我們可以通過擴充 WearableLinearLayoutManager.LayoutCallback 來實現,這裡就不展開說了。

相關文章