Wear UI
智慧手錶相對手機來說,由於使用場景不同,且螢幕較小,所以應用的設計、互動和手機是有些區別的。相對來說,佈局會更簡潔,更多地使用滑動手勢進行操作。
為此,在 Wear OS 上,官方提供了一系列新的控制元件和互動,通過它們,我們可以很方便地打造出一個適合手錶互動的應用。
新增依賴
下面用到的控制元件都來自 Wear 控制元件庫,需要在 build.gradle 檔案中新增以下依賴:
implementation 'com.android.support:wear:28.0.0'
複製程式碼
佈局
常見的錶盤有方形和圓形兩種,使用普通佈局的情況下,可能會出現這種情況:
為了使圓形錶盤上的內容不超出邊界,同時相容方形錶盤,我們可以使用 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>
複製程式碼
這樣可以在保證方形錶盤不受影響的情況下,圓形佈局的內容,不會超過顯示邊界:
導航抽屜欄
為了節省寶貴的顯示空間,通常手錶應用是沒有標題欄的,在使用 ViewPager 的時候,也沒有 TabLayout 的顯示,但因此我們無法很好的確認當前頁面。
導航欄 WearableNavigationDrawerView 就是用來解決這個問題的,我們先看看它的效果:
從手錶頂部向下滑,會出現一個導航欄,顯示當前頁面的圖示和標題。當存在多個頁面時,通過左右滑動它來切換頁面。
下面來看看它的用法,我們修改佈局檔案,使用 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() 會在底部露出一小部分操作欄,如果當前頁面是一個列表,這一部分會在列表滑動時隱藏,在列表到頂部和底部時顯示:
露出部分預設會顯示操作欄第一項的圖示,可以在佈局中新增 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。
用起來也很簡單,先在 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 是一個環形的進度條,通常用它包裹一個圓形按鈕:
可以用它來做防誤觸,使用者點選按鈕後,允許在進度條走完之前,點選取消操作。
我們把它新增到佈局中:
<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()
複製程式碼
列表
如果對比方形錶盤和圓形錶盤的手錶,他們的應用列表介面是這樣的:
在圓形錶盤上,列表是沿著錶盤左邊,曲線排列滾動的。這就是列表控制元件 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 來實現,這裡就不展開說了。