Ten dokument pokazuje, jak zachować zgodność ze stylem Glass i wdrażać typowe sprawdzone metody dotyczące interfejsu podczas korzystania z GDK.
Motyw szklany
Google Glass stosuje do oprogramowania Glassware standardowy motyw, dzięki czemu zachowuje spójność z resztą interfejsu. Motyw ma te cechy:
- Używa kroju Roboto.
- Wyświetla aktywności na pełnym ekranie bez paska stanu ani paska działań
- Zastosuj jednolite, czarne tło
Aby zastosować motyw Glass, nie deklaruj motywu w pliku manifestu Androida.
Jeśli masz niestandardowy styl dla elementów Glassware i chcesz ustawić domyślny motyw szklany dla całej reszty, możesz odziedziczyć go z elementu Theme.DeviceDefault
za pomocą atrybutu parent
:
<resources>
<style name="CustomTheme" parent="@android:style/Theme.DeviceDefault">
<!-- Theme customization goes here. -->
</style>
</resources>
Więcej informacji o tworzeniu motywów znajdziesz w przewodniku dla programistów aplikacji na Androida na temat stylów i motywów.
Karty ze szkła
Klasa CardBuilder
tworzy poprawnie sformatowane karty z uwzględnieniem zestawu właściwości. O ile to możliwe, korzystaj z układów udostępnianych przez CardBuilder.Layout
, aby Twoje treści wyglądały i wyglądały jak inne materiały w Google Glass.
Aby użyć aplikacji CardBuilder
:
- Utwórz instancję
CardBuilder
z wybranym układem z tabeliCardBuilder.Layout
. - Ustaw właściwości karty, takie jak tekst, przypis i sygnatura czasowa.
- Wywołaj
CardBuilder.getView()
, aby przekonwertować kartę na Androida,View
, lubCardBuilder.getRemoteViews()
, aby przekonwertować ją na obiektRemoteViews
. - Korzystaj z
View
w działaniach, układach, wCardScrollView
lubRemoteViews
wLiveCard
.
Wspólne funkcje interfejsu
Wiele układów dostępnych w CardBuilder
obsługuje typowe funkcje interfejsu opisane poniżej. Listę funkcji obsługiwanych przez poszczególne typy kart znajdziesz w dokumentacji poszczególnych układów na CardBuilder.Layout
.
Ikona informacji
Ikona informacji o pochodzeniu danych to opcjonalna ikona o wymiarach 36 × 36 pikseli, widoczna w prawym dolnym rogu karty i po prawej stronie sygnatury czasowej. Aby ustawić tę ikonę, wywołaj CardBuilder.setAttributionIcon()
, aby zidentyfikować aplikację, zwłaszcza na aktywnych kartach. Dzięki temu użytkownik może szybko spojrzeć na źródło informacji na danej karcie.
Wskaźnik stosu
Wskaźnik stosu, którym steruje CardBuilder.showStackIndicator()
, to zagięcie narożne widoczne w prawym górnym rogu karty. Użyj tej wartości jako wizualnego wskaźnika, który sygnalizuje, że karta reprezentuje pakiet innych kart, z których użytkownik może bezpośrednio korzystać.
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();
Układy
W przykładach poniżej pokazujemy układy dostępne przy użyciu parametru CardBuilder
.
TEXT
i TEXT_FIXED
W układzie CardBuilder.Layout.TEXT
wyświetla się tekst na całej linii, z opcjonalną mozaiką w tle. Rozmiar tekstu dynamicznie się zmienia,
aby jak najlepiej dopasować go do dostępnego miejsca.
CardBuilder.Layout.TEXT_FIXED
jest podobny, ale zmniejsza rozmiar tekstu.
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
i COLUMNS_FIXED
W układzie CardBuilder.Layout.COLUMNS
po lewej stronie karty wyświetla się mozaika obrazów lub ikona, a po prawej tekst. Rozmiar tekstu jest dynamicznie dopasowywany
do dostępnego miejsca. Aby utrzymać stały rozmiar tekstu, użyj wartości 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
W układzie CardBuilder.Layout.CAPTION
w tle znajduje się mozaika obrazów oraz krótki tekst napisów wyrównany u dołu karty. Obok napisu można też umieścić ikonę, która reprezentuje np. tożsamość osoby związanej z zawartością karty.
![](https://developers.google.cn/static/glass/images/glass-screens/card_caption.png?authuser=7&hl=pl)
![](https://developers.google.cn/static/glass/images/glass-screens/card_caption_icon.png?authuser=7&hl=pl)
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
W tle układu CardBuilder.Layout.TITLE
znajduje się mozaika obrazów z wyśrodkowanym tytułem i opcjonalną ikoną na dole. Ten układ jest często używany do reprezentowania kontaktów lub udostępniania celów. Ten układ nie obsługuje przypisów ani sygnatur czasowych.
View view = new CardBuilder(context, CardBuilder.Layout.TITLE)
.setText("TITLE Card")
.setIcon(R.drawable.ic_phone)
.addImage(R.drawable.beach)
.getView();
AUTHOR
Użyj układu CardBuilder.Layout.AUTHOR
, aby wyświetlić wiadomość lub wątek, w których zaznaczenie jest skupione na autorze. Można w nim umieścić mozaikę w tle, ikonę używaną jako awatar autora oraz nagłówek i podtytuł, w którym można podać dane identyfikacyjne.
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
Układ CardBuilder.Layout.MENU
wygląda jak standardowe menu Google Glass. Ma on wyśrodkowaną ikonę, tytuł i opcjonalny przypis. Zastosuj ten układ do ekranów potwierdzenia (np. przejście z „Usuwanie” do „Usunięte” po wybraniu przez użytkownika pozycji menu). Jeśli potrzebujesz prawdziwego menu, użyj standardowego menu opcji.
View view = new CardBuilder(context, CardBuilder.Layout.MENU)
.setText("MENU layout")
.setIcon(R.drawable.ic_phone)
.setFootnote("Optional menu description")
.getView();
EMBED_INSIDE
W układzie CardBuilder.Layout.EMBED_INSIDE
umieszczony jest własny kod XML układu niestandardowego układu w standardowym szablonie karty Google Glass. Dzięki temu możesz zaprojektować niestandardowy interfejs aplikacji z zachowaniem prawidłowego rozmieszczenia przypisu, sygnatury czasowej, ikony atrybucji i wskaźnika stosu karty, jeśli są potrzebne.
Po wywołaniu właściwości CardBuilder.getView()
użyj w wyniku przycisku findViewById()
, aby uzyskać dostęp do widoków w umieszczonym układzie. Podobnie, jeśli wywołujesz metodę CardBuilder.getRemoteViews()
, możesz manipulować widokami układu umieszczonego, przekazując ich identyfikatory bezpośrednio do metod ustawiania 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
Bardziej szczegółowy przykład znajdziesz w projekcie Apigee na GitHubie.
ALERT
Układ CardBuilder.Layout.ALERT
zawiera dużą wyśrodkowaną ikonę z wiadomością główną i przypisem. Użyj tego układu w elemencie Dialog
, aby wyświetlać w Google Glassware ważny komunikat informacyjny, ostrzeżenie lub błąd.
Poniższy przykład pokazuje implementację AlertDialog
. Gdy użytkownik kliknie kartę, zamyka kartę i otwiera ustawienia Wi-Fi:
- Utwórz zajęcia z rozszerzeniem
Dialog
. - Utwórz kartę za pomocą elementu
CardBuilder
z układemCardBuilder.Layout.ALERT
, a następnie ustaw widok treści za pomocą tej karty. (Opcjonalnie) Utwórz
GestureDetector
do obsługi gestów użytkownika na tej karcie.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); } }
(Opcjonalnie) W swojej aktywności zaimplementuj
OnClickListener
do obsługi dodatkowych procesów, gdy użytkownik kliknie reklamę. Więcej informacji o rozpoczynaniu działań związanych z ustawieniami, takich jak Wi-Fi, znajdziesz w sekcji Uruchamianie ustawień.Aby wyświetlić kartę alertu, wywołaj konstruktor
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(); ... } }
Układy XML
Oto 2 podstawowe układy kart, których możesz użyć, jeśli klasa CardBuilder nie spełnia Twoich potrzeb.
Układ główny
Ten układ definiuje standardowe dopełnienie i stopkę karty. Umieść własne widoki w pustym polu RelativeLayout
.
![](https://developers.google.cn/static/glass/images/grids/main-template.png?authuser=7&hl=pl)
<?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>
Układ lewej kolumny
Definiuje ona lewą kolumnę o długości 240 pikseli i prawą o długości 400 pikseli w postaci 2 elementów RelativeLayout
, w których można umieszczać widoki.
![](https://developers.google.cn/static/glass/images/grids/left-column-template.png?authuser=7&hl=pl)
<?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>
Wymiary standardowe
Aby zachować standardowy styl Glass, używaj tego pliku w połączeniu z poprzednimi układami lub własnymi układami. Utwórz ten plik jako res/values/dimens.xml
w swoim projekcie na Androida.
<?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>