Questo documento illustra come seguire lo stile di Glass e implementare best practice comuni per l'interfaccia utente durante l'utilizzo di GDK.
Tema vetro
Glass applica un tema standard a Glassware, rimane coerente con il resto dell'interfaccia utente. La ha le seguenti caratteristiche:
- Utilizza il carattere tipografico Roboto
- Visualizza le attività a schermo intero senza barra di stato o barra delle azioni
- Applica uno sfondo nero in tinta unita
Per applicare il tema Vetro, non dichiarare un tema nel file manifest Android.
Se hai uno stile personalizzato per alcune parti dei tuoi oggetti in vetro
e vuoi usare il tema Vetro predefinito
per tutto il resto,
eredita da Theme.DeviceDefault
con l'attributo parent
:
<resources>
<style name="CustomTheme" parent="@android:style/Theme.DeviceDefault">
<!-- Theme customization goes here. -->
</style>
</resources>
Consulta la guida per gli sviluppatori Android su Stili e temi per ulteriori informazioni sulla creazione di temi.
Schede in stile vetro
La CardBuilder
crea schede con formato corretto dato un insieme di proprietà. Utilizzare i layout
fornita da CardBuilder.Layout
quando possibile, in modo che i contenuti abbiano l'aspetto e il design di altri contenuti
Vetro.
Per usare CardBuilder
:
- Crea un'istanza di
CardBuilder
, utilizzando il layout che preferisci daCardBuilder.Layout
- Imposta le proprietà della scheda, come testo, nota a piè di pagina e timestamp.
- Chiama il numero
CardBuilder.getView()
per convertire la carta in un AndroidView
oppureCardBuilder.getRemoteViews()
per convertirlo in unRemoteViews
. - Utilizza l'
View
nelle tue attività, nei tuoi layout o in unaCardScrollView
oppure utilizzaRemoteViews
in unaLiveCard
.
Funzionalità comuni dell'interfaccia utente
Molti dei layout forniti da CardBuilder
supportano l'interfaccia utente comune
descritte di seguito. Visualizza la documentazione dei singoli layout in
CardBuilder.Layout
per un elenco delle funzionalità supportate da ciascun tipo di scheda.
Icona di attribuzione
L'icona di attribuzione è un'icona facoltativa di 36 × 36 pixel che viene visualizzata
nell'angolo in basso a destra di una scheda e a destra del timestamp. Imposta questo
icona chiamando
CardBuilder.setAttributionIcon()
identificare la tua applicazione, soprattutto nelle schede online, in modo che l'utente possa
e vedere la fonte delle informazioni su quella scheda.
Indicatore dello stack
L'indicatore dello stack, controllato
CardBuilder.showStackIndicator()
,
una piegatura ad angolo visualizzata nell'angolo in alto a destra di una scheda. Usa come
un indicatore visivo che indichi che la tua scheda rappresenta un insieme di altre schede
a cui l'utente può accedere direttamente.
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();
Layout
I seguenti esempi mostrano i layout disponibili utilizzando
CardBuilder
.
TEXT
e TEXT_FIXED
La CardBuilder.Layout.TEXT
il layout mostra il testo al vivo con un elemento
mosaico di immagini sullo sfondo. Il testo si ridimensiona in modo dinamico per adattarsi al meglio
di spazio disponibile.
CardBuilder.Layout.TEXT_FIXED
è simile ma corregge le dimensioni del testo.
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
e COLUMNS_FIXED
La
CardBuilder.Layout.COLUMNS
mostra un mosaico di immagini o un'icona nella
lato sinistro della scheda e il testo sul lato destro. Il testo viene ridimensionato in modo dinamico
in modo da soddisfare al meglio
lo spazio disponibile. Per mantenere fisse le dimensioni del testo, utilizza
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
La
CardBuilder.Layout.CAPTION
presenta un mosaico di immagini sullo sfondo
e un breve testo della didascalia allineato in fondo alla scheda. Un'icona può anche essere
posizionati accanto alla didascalia per rappresentare, ad esempio, l'identità di una persona
associati ai contenuti della scheda.
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
La
CardBuilder.Layout.TITLE
presenta un mosaico di immagini sullo sfondo
con un titolo centrato e un'icona facoltativa nella parte inferiore della scheda. Questo layout
viene spesso utilizzato per rappresentare i contatti o condividere obiettivi. La nota a piè di pagina e il timestamp sono
non supportato su questo layout.
View view = new CardBuilder(context, CardBuilder.Layout.TITLE)
.setText("TITLE Card")
.setIcon(R.drawable.ic_phone)
.addImage(R.drawable.beach)
.getView();
AUTHOR
Utilizza la
CardBuilder.Layout.AUTHOR
layout per visualizzare un messaggio o una conversazione
in cui l'attenzione è concentrata sull'autore. Supporta un mosaico di immagini sullo sfondo,
un'icona utilizzata come avatar dell'autore e un'intestazione e un sottotitolo in cui puoi
informazioni identificative.
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
La
CardBuilder.Layout.MENU
simile a un menu Glass standard. Ha un
icona e titolo centrati e nota a piè di pagina facoltativa. Utilizza questo layout per
schermate di conferma (passaggio da "Eliminazione" a "Eliminato" dopo che
seleziona una voce di menu, ad esempio). Se hai bisogno di un menù reale, usa una
nel menu opzioni standard.
View view = new CardBuilder(context, CardBuilder.Layout.MENU)
.setText("MENU layout")
.setIcon(R.drawable.ic_phone)
.setFootnote("Optional menu description")
.getView();
EMBED_INSIDE
La
CardBuilder.Layout.EMBED_INSIDE
incorpora un XML di layout personalizzato di tua scelta nel pannello Glass standard
modello di scheda. Ciò ti consente di progettare una UI personalizzata per la tua applicazione,
posizione corretta per la nota a piè di pagina, il timestamp, l'icona di attribuzione e
dell'indicatore dello stack, se necessario.
Dopo la chiamata
CardBuilder.getView()
,
utilizzare
findViewById()
sul risultato per accedere alle visualizzazioni all'interno del layout incorporato. Allo stesso modo, se
chiamata
CardBuilder.getRemoteViews()
,
puoi manipolare le visualizzazioni del layout incorporato trasmettendone gli ID direttamente
nel
RemoteViews
metodi di impostazione.
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
Per un esempio più dettagliato, consulta la pagina GitHub Progetto apiDemo.
ALERT
La
CardBuilder.Layout.ALERT
layout contiene una grande icona centrata con
messaggio principale e nota a piè di pagina. Utilizza questo layout in una
Da Dialog
a
mostrare un messaggio informativo importante, un avviso o un errore in Glassware.
L'esempio seguente mostra un'implementazione di AlertDialog
e ignora il
e apre le impostazioni Wi-Fi quando l'utente la tocca:
- Crea un corso che estenda
Dialog
. - Crea la scheda utilizzando
CardBuilder
con il layoutCardBuilder.Layout.ALERT
e imposta la visualizzazione dei contenuti con questa scheda. (Facoltativo) Crea una
GestureDetector
per gestire i gesti dell'utente su questa scheda.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); } }
(Facoltativo) Nella tua attività, implementa una
OnClickListener
per gestire eventuali flussi aggiuntivi quando l'utente tocca il pulsante. Per ulteriori informazioni avviare attività relative alle impostazioni come il Wi-Fi, controlla Avvio delle impostazioni.Chiama il costruttore
AlertDialog
per visualizzare la scheda di avviso.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(); ... } }
Layout XML
Ecco due layout di schede di base che puoi utilizzare se la classe CardBuilder non soddisfano le tue esigenze.
Layout principale
Questo layout definisce la spaziatura interna e il piè di pagina standard di una scheda. Inserisci la tua
visualizzazioni nel campo RelativeLayout
vuoto.
<?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>
Layout colonna a sinistra
Definisce una colonna sinistra di 240 px e una colonna destra di 400 px sotto forma di due RelativeLayout
in cui puoi includere le tue visualizzazioni.
<?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>
Dimensioni standard
Utilizza questo file insieme ai layout precedenti o ai tuoi layout per
per rispettare lo stile standard del vetro. Crea questo file come
res/values/dimens.xml
nel tuo progetto Android.
<?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>