このドキュメントでは、Glass のスタイルに沿って、UI を最適化してユーザー エクスペリエンスを最適化する方法について説明します。以下の UI 要素について説明します。
テーマ
Glass のテーマには、次のような特長があります。
- アクションバーなしでアクティビティを全画面表示します。
- 黒一色の背景を適用します。
- カラーエッジ効果の明るい色を設定します。
- 白色のテキストの色を適用します。
Glass の推奨テーマ設定は次のとおりです。
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar"> <item name="android:windowBackground">@android:color/black</item> <item name="android:colorEdgeEffect">@android:color/white</item> <item name="android:textColor">@android:color/white</item> </style>
XML レイアウト
フラグメントにインフレートできる基本的なカード レイアウトには次の 2 つがあります。
メイン レイアウト
このレイアウトでは、カードに推奨される標準のパディングとフッターを定義します。独自のビューは空の FrameLayout
に配置します。
XML レイアウトの例を次に示します。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/body_layout" android:layout_width="0dp" android:layout_height="0dp" android:layout_margin="@dimen/glass_card_margin" app:layout_constraintBottom_toTopOf="@id/footer" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <!-- Put your widgets inside this FrameLayout. --> </FrameLayout> <!-- The footer view will grow to fit as much content as possible while the timestamp view keeps its width. If the footer text is too long, it will be ellipsized with a 40dp margin between it and the timestamp. --> <TextView android:id="@+id/footer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/glass_card_margin" android:layout_marginEnd="@dimen/glass_card_margin" android:layout_marginBottom="@dimen/glass_card_margin" android:ellipsize="end" android:singleLine="true" android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/timestamp" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/timestamp" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/glass_card_margin" android:layout_marginBottom="@dimen/glass_card_margin" android:ellipsize="end" android:singleLine="true" android:textAlignment="viewEnd" android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
左側の列のレイアウト
このレイアウトでは、ビューを配置できる 2 つの FrameLayout
クラスの形式で、左 3 分の 1 の列と右 2 分の 3 の右の列を定義しています。下の図の例をご覧ください。
XML レイアウトの例を次に示します。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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"> <FrameLayout android:id="@+id/left_column" android:layout_width="0dp" android:layout_height="match_parent" android:background="#303030" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintWidth_percent=".333"> <!-- Put widgets for the left column inside this FrameLayout. --> </FrameLayout> <FrameLayout android:id="@+id/right_column" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="@dimen/glass_card_two_column_margin" android:layout_marginStart="@dimen/glass_card_two_column_margin" android:layout_marginBottom="@dimen/glass_card_two_column_margin" android:layout_marginEnd="@dimen/glass_card_margin" app:layout_constraintBottom_toTopOf="@id/footer" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/left_column" app:layout_constraintTop_toTopOf="parent"> <!-- Put widgets for the right column inside this FrameLayout. --> </FrameLayout> <!-- The footer view will grow to fit as much content as possible while the timestamp view keeps its width. If the footer text is too long, it will be ellipsized with a 40dp margin between it and the timestamp. --> <TextView android:id="@+id/footer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/glass_card_margin" android:layout_marginEnd="@dimen/glass_card_margin" android:layout_marginBottom="@dimen/glass_card_margin" android:ellipsize="end" android:singleLine="true" android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/timestamp" app:layout_constraintStart_toEndOf="@id/left_column" /> <TextView android:id="@+id/timestamp" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/glass_card_margin" android:layout_marginBottom="@dimen/glass_card_margin" android:ellipsize="end" android:singleLine="true" android:textAlignment="viewEnd" android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
標準ディメンション
前のレイアウトまたは独自のレイアウトと組み合わせて使用し、Glass' 標準スタイルに準拠したファイルを作成します。このファイルを Android プロジェクトで res/values/dimens.xml
として作成します。
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- The recommended margin for the top, left, and right edges of a card. --> <dimen name="glass_card_margin">40dp</dimen> <!-- The recommended margin between the bottom of the card and the footer. --> <dimen name="glass_card_footer_margin">50dp</dimen> <!-- The recommended margin for the left column of the two-column card. --> <dimen name="glass_card_two_column_margin">30dp</dimen> </resources>
メニュー
メニューの作成には RecyclerView
を使用することをおすすめします。Android Studio プロジェクト リソースの標準の Android メニュー ファイルに基づいています。Android では、標準のメニュー作成をオーバーライドして、実装に置き換えることができます。方法は次のとおりです。
RecyclerView
を使用してレイアウトを作成し、Activity
のビューとして設定します。- 新たに作成されたメニュー項目のコレクションを使用するように
RecyclerView
とそのアダプタを設定します。 onCreateOptionsMenu
メソッドをオーバーライドします。- メニューをインフレートして、各メニュー項目のコレクションに新しい要素を追加します。
- アダプタの
notifyDataSetChanged
メソッドを呼び出します。
Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean { val menuResource = intent .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE) if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) { menuInflater.inflate(menuResource, menu) for (i in 0 until menu.size()) { val menuItem = menu.getItem(i) menuItems.add( GlassMenuItem( menuItem.itemId, menuItem.icon, menuItem.title.toString() ) ) adapter.notifyDataSetChanged() } } return super.onCreateOptionsMenu(menu) }
Java
@Override public boolean onCreateOptionsMenu(Menu menu) { final int menuResource = getIntent() .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE); if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) { final MenuInflater inflater = getMenuInflater(); inflater.inflate(menuResource, menu); for (int i = 0; i < menu.size(); i++) { final MenuItem menuItem = menu.getItem(i); menuItems.add( new GlassMenuItem(menuItem.getItemId(), menuItem.getIcon(), menuItem.getTitle().toString())); adapter.notifyDataSetChanged(); } } return super.onCreateOptionsMenu(menu); }
OnScrollListener
をLayoutManager
およびSnapHelper
と併用して、どのオプションが選択されたかを判断します。TAP
ジェスチャーをリッスンして、メニュー項目の選択イベントを処理します。- 選択したメニュー項目に関する情報を使用して
Intent
を作成します。 - このアクティビティの結果を設定して終了します。
- メニューを配置するフラグメントまたはアクティビティから
startActivityForResult
を呼び出します。この目的のためにTAP
ジェスチャーを使用します。 - 呼び出し元のフラグメントまたはアクティビティの
onActivityResult
をオーバーライドして、選択したメニュー項目を処理します。
ガイドライン
メニュー レイアウトをセットアップする方法のヒントを以下に示します。
- テキスト サイズ:
64sp
- 背景色:
#96000000
- マテリアル アイコンのサイズを
64dpx64dp
にします。 windowIsTranslucent
テーマフラグをtrue
に設定します。
次の図は、カスタマイズされたメニュー レイアウトの例です。
カードサンプルアプリで実装の詳細を確認します。
スワイプ可能なページ
Glass ディスプレイとタッチパッドが連動し、スワイプ可能なカードを便利な方法で表示します。標準の Android ViewPager
API を使用すると、アクティビティでスワイプ可能なページを作成できます。
Android ViewPager
を使用してカードや画面をスクロールする方法について詳しくは、画面スライドのトレーニング ドキュメントをご覧ください。