このドキュメントでは、Glass のスタイルを実践し、GDK を使用する際の一般的な UI のベスト プラクティスを実装する方法について説明します。
Glass のテーマ
Glass は Glassware に標準のテーマを適用するため、残りのユーザー インターフェースとの一貫性が維持されます。テーマには次の特性があります。
- Roboto Typeface を使用する
- ステータスバーやアクションバーを使わずにアクティビティを全画面表示します
- 黒一色の背景を適用
Glass テーマを適用するには、Android マニフェストでテーマを宣言しないでください。
Glassware の一部にカスタム スタイルがあり、その他すべてにデフォルトの Glass テーマが必要な場合は、parent
属性を持つ Theme.DeviceDefault
から継承します。
<resources>
<style name="CustomTheme" parent="@android:style/Theme.DeviceDefault">
<!-- Theme customization goes here. -->
</style>
</resources>
テーマの作成について詳しくは、Android デベロッパー ガイドのスタイルとテーマをご覧ください。
Glass スタイルのカード
CardBuilder
クラスは、一連のプロパティに基づいて適切な形式のカードを作成します。可能な限り、CardBuilder.Layout
が提供するレイアウトを使用して、コンテンツが Glass の他のコンテンツと同じように見えるようにしてください。
CardBuilder
を使用するには:
CardBuilder
のインスタンスを作成し、CardBuilder.Layout
から目的のレイアウトを指定します。- カードのプロパティ(テキスト、脚注、タイムスタンプなど)を設定します。
- カードを Android
View
に変換するにはCardBuilder.getView()
を呼び出し、RemoteViews
オブジェクトに変換するにはCardBuilder.getRemoteViews()
を呼び出します。 - アクティビティ、レイアウト、
CardScrollView
のView
を使用するか、LiveCard
のRemoteViews
を使用します。
一般的な UI 機能
CardBuilder
が提供するレイアウトの多くは、以下で説明する一般的なユーザー インターフェース機能をサポートしています。各タイプのカードでサポートされている機能の一覧については、CardBuilder.Layout
の個々のレイアウトのドキュメントをご覧ください。
アトリビューション アイコン
アトリビューション アイコンは 36×36 ピクセルのオプションです。カードの右下隅とタイムスタンプの右側に表示されます。CardBuilder.setAttributionIcon()
を呼び出してこのアイコンを設定すると、特にライブカード上でアプリを識別できるため、ユーザーはそのカードに記載されている情報のソースをすばやく確認できます。
スタック インジケーター
スタック インジケーター(CardBuilder.showStackIndicator()
によって制御)は、カードの右上隅に表示されることがあります。カードは、ユーザーが直接タップできる他のカードのバンドルを表す視覚的インジケーターとして使用します。
View view = new CardBuilder(context, CardBuilder.Layout.TEXT)
.setText("A stack indicator can be added to the corner of a card...")
.setAttributionIcon(R.drawable.ic_smile)
.showStackIndicator(true)
.getView();
レイアウト
次の例は、CardBuilder
を使用して利用できるレイアウトを示しています。
TEXT
、TEXT_FIXED
CardBuilder.Layout.TEXT
レイアウトでは、余白のないテキストが表示され、必要に応じて画像にモザイク模様が付きます。テキストは、利用可能なスペースに合わせて動的にサイズ変更されます。
CardBuilder.Layout.TEXT_FIXED
は似ていますが、テキストが小さいサイズに修正されます。
View view1 = new CardBuilder(context, CardBuilder.Layout.TEXT)
.setText("This is the TEXT layout. The text size will adjust dynamically.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.getView();
View view2 = new CardBuilder(context, CardBuilder.Layout.TEXT)
.setText("You can also add images to the background of a TEXT card.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.image1)
.addImage(R.drawable.image2)
.addImage(R.drawable.image3)
.addImage(R.drawable.image4)
.addImage(R.drawable.image5)
.getView();
View view3 = new CardBuilder(context, CardBuilder.Layout.TEXT_FIXED)
.setText("This is the TEXT_FIXED layout. The text size is always the same.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.getView();
COLUMNS
、COLUMNS_FIXED
CardBuilder.Layout.COLUMNS
レイアウトでは、カードの左側に画像のモザイクまたはアイコン、右側にテキストが表示されます。テキストは、利用可能なスペースに合わせて動的に調整されます。テキストサイズを固定するには、CardBuilder.Layout.COLUMNS_FIXED
を使用します。
View view1 = new CardBuilder(context, CardBuilder.Layout.COLUMNS)
.setText("This is the COLUMNS layout with dynamic text.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.image1)
.addImage(R.drawable.image2)
.addImage(R.drawable.image3)
.addImage(R.drawable.image4)
.addImage(R.drawable.image5)
.getView();
View view2 = new CardBuilder(context, CardBuilder.Layout.COLUMNS)
.setText("You can even put a centered icon on a COLUMNS card instead of a mosaic.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.setIcon(R.drawable.ic_wifi)
.getView();
View view3 = new CardBuilder(context, CardBuilder.Layout.COLUMNS_FIXED)
.setText("This is the COLUMNS_FIXED layout. The text size is always the same.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.image1)
.addImage(R.drawable.image2)
.addImage(R.drawable.image3)
.addImage(R.drawable.image4)
.addImage(R.drawable.image5)
.getView();
CAPTION
CardBuilder.Layout.CAPTION
レイアウトでは、背景に画像のモザイクが使用され、短い字幕テキストはカードの下部に配置されています。また、字幕の横にアイコンを配置して、カードのコンテンツに関連付けられている人物の ID などを表すこともできます。
![](https://developers.google.cn/static/glass/images/glass-screens/card_caption.png?hl=ja)
![](https://developers.google.cn/static/glass/images/glass-screens/card_caption_icon.png?hl=ja)
View view1 = new CardBuilder(context, CardBuilder.Layout.CAPTION)
.setText("The caption layout.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.beach)
.setAttributionIcon(R.drawable.ic_smile)
.getView();
View view2 = new CardBuilder(context, CardBuilder.Layout.CAPTION)
.setText("The caption layout with an icon.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.beach)
.setIcon(R.drawable.ic_avatar)
.setAttributionIcon(R.drawable.ic_smile)
.getView();
TITLE
CardBuilder.Layout.TITLE
レイアウトでは、画像にモザイクがあり、中央にタイトルが配置され、カード下部にオプションのアイコンがあります。このレイアウトは、連絡先を表す場合やターゲットを共有する場合によく使用されます。このレイアウトでは、脚注とタイムスタンプはサポートされていません。
View view = new CardBuilder(context, CardBuilder.Layout.TITLE)
.setText("TITLE Card")
.setIcon(R.drawable.ic_phone)
.addImage(R.drawable.beach)
.getView();
AUTHOR
CardBuilder.Layout.AUTHOR
レイアウトを使用して、作成者にフォーカスしているメッセージや会話を表示します。背景のモザイク 画像、著者のアバターとして使用されているアイコン、識別情報のリストを表示する見出しと小見出しをサポートしています。
View view = new CardBuilder(context, CardBuilder.Layout.AUTHOR)
.setText("The AUTHOR layout lets you display a message or conversation "
+ " with a focus on the author.")
.setIcon(R.drawable.ic_avatar)
.setHeading("Joe Lastname")
.setSubheading("Mountain View, California")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.getView();
MENU
CardBuilder.Layout.MENU
レイアウトは、標準の Glass メニューに似ています。アイコンとタイトルが中央に配置され、脚注がオプションとして表示されています。このレイアウトは、確認メニュー(ユーザーがメニュー項目を選択した後などで [削除] から [削除済み] に移行するなど)に使用します。実際のメニューが必要な場合は、代わりに標準のオプション メニューを使用する必要があります。
View view = new CardBuilder(context, CardBuilder.Layout.MENU)
.setText("MENU layout")
.setIcon(R.drawable.ic_phone)
.setFootnote("Optional menu description")
.getView();
EMBED_INSIDE
CardBuilder.Layout.EMBED_INSIDE
レイアウトは、独自のデザインのカスタム レイアウト XML を標準の Glass カード テンプレートに埋め込みます。これにより、アプリのカスタム UI を設計できますが、必要に応じてカードの脚注、タイムスタンプ、アトリビューション アイコン、スタック インジケーターを適切に配置できます。
CardBuilder.getView()
を呼び出した後、結果で findViewById()
を使用して、埋め込みレイアウト内のビューにアクセスします。同様に、CardBuilder.getRemoteViews()
を呼び出して、埋め込みレイアウトのビューを操作するには、その ID を RemoteViews
セッター メソッドに直接渡します。
View view = new CardBuilder(context, CardBuilder.Layout.EMBED_INSIDE)
.setEmbeddedLayout(R.layout.food_table)
.setFootnote("Foods you tracked")
.setTimestamp("today")
.getView();
TextView textView1 = (TextView) view.findViewById(R.id.text_view_1);
textView1.setText("Water");
// ...and so on
より詳細な例については、GitHub の ApiDemo プロジェクトをご覧ください。
ALERT
CardBuilder.Layout.ALERT
レイアウトには、メインの中央に大きなアイコンと脚注が付いたアイコンがあります。このレイアウトを Dialog
で使用すると、Glassware で重要な情報、警告、エラーを表示できます。
次の例は、AlertDialog
の実装を示しています。ユーザーがカードをタップすると、カードを閉じて Wi-Fi 設定を開きます。
Dialog
を拡張するクラスを作成します。CardBuilder
を使用してCardBuilder.Layout.ALERT
レイアウトでカードを作成し、そのカードでコンテンツ ビューを設定します。(省略可)このカードでのユーザー ジェスチャーを処理する
GestureDetector
を作成します。public class AlertDialog extends Dialog { private final DialogInterface.OnClickListener mOnClickListener; private final AudioManager mAudioManager; private final GestureDetector mGestureDetector; /** * Handles the tap gesture to call the dialog's * onClickListener if one is provided. */ private final GestureDetector.BaseListener mBaseListener = new GestureDetector.BaseListener() { @Override public boolean onGesture(Gesture gesture) { if (gesture == Gesture.TAP) { mAudioManager.playSoundEffect(Sounds.TAP); if (mOnClickListener != null) { // Since Glass dialogs do not have buttons, // the index passed to onClick is always 0. mOnClickListener.onClick(AlertDialog.this, 0); } return true; } return false; } }; public AlertDialog(Context context, int iconResId, int textResId, int footnoteResId, DialogInterface.OnClickListener onClickListener) { super(context); mOnClickListener = onClickListener; mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mGestureDetector = new GestureDetector(context).setBaseListener(mBaseListener); setContentView(new CardBuilder(context, CardBuilder.Layout.ALERT) .setIcon(iconResId) .setText(textResId) .setFootnote(footnoteResId) .getView()); } /** Overridden to let the gesture detector handle a possible tap event. */ @Override public boolean onGenericMotionEvent(MotionEvent event) { return mGestureDetector.onMotionEvent(event) || super.onGenericMotionEvent(event); } }
(省略可)アクティビティで、ユーザーがタップしたときの追加のフローを処理する
OnClickListener
を実装します。Wi-Fi などの設定アクティビティの開始について詳しくは、設定を開始するをご覧ください。AlertDialog
コンストラクタを呼び出して、アラートカードを表示します。public class MyActivity extends Activity { ... private final DialogInterface.OnClickListener mOnClickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int button) { // Open WiFi Settings startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); } }; @Override protected void onCreate(Bundle bundle) { ... new AlertDialog(context, R.drawable.ic_cloud_sad_150, R.string.alert_text, R.string.alert_footnote_text, mOnClickListener).show(); ... } }
XML レイアウト
CardBuilder クラスがニーズに合わない場合に使用可能な基本的なカード レイアウトを 2 つ紹介します。
メイン レイアウト
このレイアウトでは、カードの標準のパディングとフッターを定義します。空の RelativeLayout
には独自のビューを配置します。
![](https://developers.google.cn/static/glass/images/grids/main-template.png?hl=ja)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:id="@+id/body_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/glass_card_body_height"
android:layout_marginLeft="@dimen/glass_card_margin"
android:layout_marginTop="@dimen/glass_card_margin"
android:layout_marginRight="@dimen/glass_card_margin"
tools:ignore="UselessLeaf"
>
<!-- Put your widgets inside this RelativeLayout. -->
</RelativeLayout>
<LinearLayout
android:id="@+id/footer_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|left"
android:layout_marginLeft="@dimen/glass_card_margin"
android:layout_marginBottom="@dimen/glass_card_footer_margin"
android:layout_marginRight="@dimen/glass_card_margin"
android:orientation="horizontal"
>
<!-- The footer view will grow to fit as much content as possible while the
timestamp view keeps a fixed width. If the footer text is too long, it
will be ellipsized with a 40px margin between it and the timestamp. -->
<TextView
android:id="@+id/footer"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
<TextView
android:id="@+id/timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/glass_card_margin"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
</LinearLayout>
</FrameLayout>
左列のレイアウト
これにより、ビューを配置できる 2 つの RelativeLayout
の形式で、240 ピクセルの左の列と 400 ピクセルの右の列が定義されます。
![](https://developers.google.cn/static/glass/images/grids/left-column-template.png?hl=ja)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:id="@+id/left_column"
android:layout_width="@dimen/glass_card_left_column_width"
android:layout_height="match_parent"
>
<!-- Put widgets for the left column inside this RelativeLayout. -->
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="@dimen/glass_card_body_height"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="@dimen/glass_card_two_column_margin"
android:layout_marginRight="@dimen/glass_card_margin"
android:layout_marginTop="@dimen/glass_card_margin"
android:layout_toRightOf="@+id/left_column"
tools:ignore="UselessLeaf"
>
<!-- Put widgets for the right column inside this RelativeLayout. -->
</RelativeLayout>
<LinearLayout
android:id="@+id/footer_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_gravity="bottom|left"
android:layout_marginBottom="@dimen/glass_card_footer_margin"
android:layout_marginLeft="@dimen/glass_card_two_column_margin"
android:layout_marginRight="@dimen/glass_card_margin"
android:layout_toRightOf="@+id/left_column"
android:orientation="horizontal"
>
<!--
The footer view will grow to fit as much content as possible while the
timestamp view keeps a fixed width. If the footer text is too long, it
will be ellipsized with a 40px margin between it and the timestamp.
-->
<TextView
android:id="@+id/footer"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
<TextView
android:id="@+id/timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/glass_card_margin"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
</LinearLayout>
</RelativeLayout>
標準サイズ
標準の 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">40px</dimen>
<!-- The recommended margin between the bottom of the card and the footer. This is
an adjusted value so that the baseline of the text in the footer sits 40px
from the bottom of the card, matching the other margins. -->
<dimen name="glass_card_footer_margin">33px</dimen>
<!-- The recommended margin for the left column of the two-column card. -->
<dimen name="glass_card_two_column_margin">30px</dimen>
<!-- The maximum height of the body content inside a card. -->
<dimen name="glass_card_body_height">240px</dimen>
<!-- The width of the left column in the two-column layout. -->
<dimen name="glass_card_left_column_width">240px</dimen>
</resources>