Wearable UI Library について
Android Wear向けのアプリケーションを提供する場合、フォンやタブレットといった現行のUIデザインで実装しようとすると使用ケースやデバイスが異なるため、見辛い、操作しにくいといったことに陥りがちです。
Wearデザインに適したアプリを容易に開発者が実装できるように、Wear向けのUIコンポーネントをまとめたライブラリが(Wearable UI Library)提供されています。
導入方法はbuild.gradleファイルに以下のコードを追加するだけです。
compile 'com.google.android.support:wearable:+'`
Wearable UI Library で提供されているコンポーネント
提供さているコンポーネントを列挙していきます。全てではありませんが簡単な説明をまとめています。ここでは四角型のWearデバイスをShapeデバイス、丸型のWearデバイスをRoundデバイスと呼んでいます。
サンプルコードはhttps://github.com/Tazake/SampleWearUIにあります。
BoxInsetLayout
BoxInsetLayoutは、画面の形状を認識するFrameLayoutです。
Roundデバイス画面上に入る正方形の中に子Viewを配置します。
子Viewにlayout_box属性に正方形の端( top , left , right , button , all )を指定すると、子Viewの指定した端の部分がはみ出ないように調整されます。
Shapeデバイスの場合は指定しても無視されます。
<android.support.wearable.view.BoxInsetLayout
android:id="@+id/box_inset_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_launcher"
app:layout_box="top|left"/>
</android.support.wearable.view.BoxInsetLayout>
ShapeデバイスとRoundデバイスでレイアウトを変更する方法は、BoxInsetLayout以外にはWatchViewStubでレイアウトファイルを切り替える方法と、onApplyWindowInsetsでJavaコード上でレイアウトを調整する方法があります。
CardFrame と CardScrollView
CardFrameは背景が白く、白角丸でドロップシャドウがかかったカードスタイルを提供します。
CardFrame内に各Viewを配置することでカードスタイルのレイアウトを作成することができます。
但し、スクロールはできないので必要な場合はCardScrollViewも使用することになります。
CardScrollViewはCardFrameにスクロール機能を提供するViewです。CardScrollViewの子要素にはCardFrameのみ配置することができます。
<android.support.wearable.view.CardScrollView
android:id="@+id/grid_card_scroll_view"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.wearable.view.CardFrame
android:id="@+id/grid_card_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="Page1"
android:textColor="#333333"/>
<TextView ... />
</LinearLayout>
</android.support.wearable.view.CardFrame>
</android.support.wearable.view.CardScrollView>
カードスタイルのデザインを表現するするには、CardScrollView内にCardFrameを配置しての使用。もしくは、CardFragment(内部ではCardScrollViewとCardFrameを使用している)を使用するケースが大半になります。
CircledImageView
円で囲まれた画像です。
円の色、半径、枠線と枠線の幅を指定することができます。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<android.support.wearable.view.CircledImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@android:drawable/ic_menu_rotate"
app:circle_border_color="#999999"
app:circle_border_width="2dp"
app:circle_color="#3d3d3d"
app:circle_radius="30dp"
app:circle_radius_pressed="60dp"/>
</FrameLayout>
ConfirmationActivity
ユーザーがアクションを完了した後に、確認のアニメーションを表示するActivityです。
アクションの成功、失敗、phoneで開くといったものが提供されています。
ConfirmationActivityを使用するにはAndroidManifest.xmlに宣言を追加する必要があります。
<activity android:name="android.support.wearable.activity.ConfirmationActivity" />
表示する時はIntentを生成してstartActivityを呼ぶだけです。
Intent intent = new Intent(this, ConfirmationActivity.class);
intent.putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE, ConfirmationActivity.SUCCESS_ANIMATION);
intent.putExtra(ConfirmationActivity.EXTRA_MESSAGE, getString(R.string.confirm_success));
startActivity(intent);
Intentのextraに各種パラメータを指定することで、アニメーションの種類、メッセージを変更することができます。
パラメータ名 | 内容 |
---|---|
EXTRA_ANIMATION_TYPE | アニメーションの種類(SUCCESS_ANIMATION、SUCCESS_ANIMATION,OPEN_ON_PHONE_ANIMATION) |
EXTRA_MESSAGE | 表示するメッセージ |
デフォルトだと、アニメーションはSUCCESS_ANIMATION、EXTRA_MESSAGEは未設定となっています。
DismissOverlayView
long-press-to-dismissを実装したViewです。
エラー情報を画面上にフルスクリーンで覆い被さるように表示します。
GestureDetectorでロングタップを検知し、DismissOverlayViewを表示するように使用します。
DismissOverlayViewをタップすると自動的に表示しているActivityは閉じられます。
private GestureDetectorCompat mGestureDetector;
private DismissOverlayView mDismissOverlayView;
private class LongPressListener extends GestureDetector.SimpleOnGestureListener {
@Override
public void onLongPress(MotionEvent event) {
mDismissOverlayView.show();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dismiss_overlay_view);
mGestureDetector = new GestureDetectorCompat(DismissOverlayViewActivity.this, new LongPressListener());
mDismissOverlayView = (DismissOverlayView) findViewById(R.id.dismiss_overlay);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
return mGestureDetector.onTouchEvent(event) || super.dispatchTouchEvent(event);
}
GridViewPager
上下左右に移動できるViewPagerです。
GridPagerAdapterを実装して使用します。
WatchViewStub
デバイスの形状の違いを判定して、レイアウトを変更するコンポーネントです。
Wearプロジェクトを作成するとデフォルトで組み込まれています。
WearableListView
小さい画面であるウェアラブルデバイスに最適化されたListViewです。
縦にスクロールできるリストが表示され、ユーザーがスクロールを止めると、近いリストアイテムに自動的にsnapします。
RecyclerViewを継承して作成されており、ListViewとは使用方法が少し異なります。
<android.support.wearable.view.WearableListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
private WearableListView mListView;
mListView.setAdapter(new SampleAdapter(this, mWidgetList));
mListView.setHasFixedSize(true);
mListView.setClickListener(new WearableListView.ClickListener() {
@Override
public void onClick(WearableListView.ViewHolder viewHolder) {
//do something }
@Override
public void onTopEmptyRegionClick() {
//do something
});
private class SampleAdapter extends WearableListView.Adapter {
private LayoutInflater mLayoutInflater;
private List<WearUI> mWidgetList;
public SampleAdapter(Context context, List<WearUI> widgetList) {
super();
mLayoutInflater = LayoutInflater.from(context);
mWidgetList = widgetList;
}
@Override
public WearableListView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = mLayoutInflater.inflate(android.R.layout.simple_list_item_1, viewGroup, false);
MyViewHolder viewHolder = new MyViewHolder(v);
return viewHolder;
}
@Override
public void onBindViewHolder(WearableListView.ViewHolder viewHolder, int position) {
MyViewHolder myViewHolder = (MyViewHolder) viewHolder;
String data = mWidgetList.get(position).getWidgetName(getApplicationContext());
myViewHolder.text.setText(data);
}
@Override
public int getItemCount() {
return mWidgetList.size();
}
}
static class MyViewHolder extends WearableListView.ViewHolder {
public TextView text;
public MyViewHolder(View v) {
super(v);
text = (TextView) v.findViewById(android.R.id.text1);
}
}