En este documento, se explica cómo seguir el estilo de Glass. e implementar prácticas recomendadas comunes de IU cuando se usa el GDK.
Tema de vidrio
Glass aplica un tema estándar a tu Glassware; por lo tanto, y mantenga la coherencia con el resto de la interfaz de usuario. El el tema tiene las siguientes características:
- Usa el tipo de letra Roboto.
- Muestra las actividades en pantalla completa, sin barra de estado ni de acciones.
- Aplica un fondo negro sólido
Para aplicar el tema de Glass, no declares un tema en tu manifiesto de Android.
Si tienes un estilo personalizado para partes de tus cristales
y quieres el tema de Glass predeterminado para todo lo demás,
hereda de Theme.DeviceDefault
con el atributo parent
:
<resources>
<style name="CustomTheme" parent="@android:style/Theme.DeviceDefault">
<!-- Theme customization goes here. -->
</style>
</resources>
Consulta la guía para desarrolladores de Android sobre Estilos y temas para obtener más información sobre cómo crear temas.
Tarjetas con estilo de vidrio
El CardBuilder
crea tarjetas con el formato correcto a partir de un conjunto de propiedades. Usa los diseños
proporcionada por CardBuilder.Layout
siempre que sea posible para que su contenido se vea como otro contenido en
Vidrio.
Para usar CardBuilder
, haz lo siguiente:
- Crea una instancia de
CardBuilder
y asígnale el diseño que quieras desdeCardBuilder.Layout
- Establece las propiedades de la tarjeta, como el texto, la nota al pie y la marca de tiempo.
- Llama a
CardBuilder.getView()
para convertir la tarjeta en un modeloView
oCardBuilder.getRemoteViews()
para convertirlo en unRemoteViews
. - Usa
View
en tus actividades, diseños o en unaCardScrollView
o usa laRemoteViews
en unLiveCard
.
Funciones comunes de la IU
Muchos de los diseños que proporciona CardBuilder
admiten la interfaz de usuario común.
que se describen a continuación. Consulta la documentación de los diseños individuales en
CardBuilder.Layout
para obtener una lista de las funciones compatibles con cada tipo de tarjeta.
Ícono de atribución
El ícono de atribución es un ícono opcional de 36 × 36 píxeles que aparece en
en la esquina inferior derecha de una tarjeta y a la derecha de la marca de tiempo. Establecer
ícono llamando
CardBuilder.setAttributionIcon()
para identificar tu aplicación, especialmente con tarjetas “live”, a fin de que un usuario pueda
y verás la fuente de la información de esa tarjeta.
Indicador de pila
El indicador de pila, controlado por
CardBuilder.showStackIndicator()
:
es un pliegue de esquina que aparece en la esquina superior derecha de una tarjeta. Usar esto como
un indicador visual de que tu tarjeta representa un conjunto de otras tarjetas que el
al que el usuario puede acceder directamente.
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();
Diseños
En los siguientes ejemplos, se muestran los diseños disponibles con el
CardBuilder
TEXT
y TEXT_FIXED
El CardBuilder.Layout.TEXT
muestra texto sin sangrado completo con una opción
mosaico de imágenes en el fondo. El texto cambia de tamaño dinámicamente para ajustarse mejor al
espacio disponible.
CardBuilder.Layout.TEXT_FIXED
es similar, pero corrige su texto a un tamaño más pequeño.
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
y COLUMNS_FIXED
El
CardBuilder.Layout.COLUMNS
muestra un mosaico o un ícono de imágenes en el
lado izquierdo de la tarjeta y texto en el lado derecho. El tamaño del texto se establece de forma dinámica.
para que se adapte mejor al espacio disponible. Para mantener fijo el tamaño del texto, usa
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
El
CardBuilder.Layout.CAPTION
el diseño tiene un mosaico de imágenes en el fondo
y un breve texto de las leyendas alineado en la parte inferior de la tarjeta. Un ícono también puede ser
colocado junto a la leyenda para representar, por ejemplo, la identidad de una persona
asociada con el contenido de la tarjeta.
![](https://developers.google.cn/static/glass/images/glass-screens/card_caption.png?hl=es-419)
![](https://developers.google.cn/static/glass/images/glass-screens/card_caption_icon.png?hl=es-419)
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
El
CardBuilder.Layout.TITLE
el diseño tiene un mosaico de imágenes en el fondo
con un título centrado y un ícono opcional en la parte inferior de la tarjeta. Este diseño
suele usarse para representar contactos o compartir objetivos. La nota al pie y la marca de tiempo son
no es compatible con este diseño.
View view = new CardBuilder(context, CardBuilder.Layout.TITLE)
.setText("TITLE Card")
.setIcon(R.drawable.ic_phone)
.addImage(R.drawable.beach)
.getView();
AUTHOR
Usa el
CardBuilder.Layout.AUTHOR
diseño para mostrar un mensaje o una conversación
cuyo enfoque está en el autor. Admite un mosaico de imágenes en segundo plano,
un icono utilizado como avatar del autor, y un encabezado y subtítulo donde puedes
en una lista con la información
de identificación correspondiente.
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
El
CardBuilder.Layout.MENU
luce como un menú de vidrio estándar. Tiene un
el ícono y el título centrados, y una nota al pie opcional. Usar este diseño para
pantallas de confirmación (transición de "Eliminado" a "Eliminado" después de que el usuario
selecciona un elemento del menú, por ejemplo). Si necesitas un menú real, debes usar un
el menú de opciones estándar.
View view = new CardBuilder(context, CardBuilder.Layout.MENU)
.setText("MENU layout")
.setIcon(R.drawable.ic_phone)
.setFootnote("Optional menu description")
.getView();
EMBED_INSIDE
El
CardBuilder.Layout.EMBED_INSIDE
Layout incorpora un XML de tu propio diseño personalizado en la aplicación Glass estándar.
plantilla de tarjeta. Esto te permite diseñar una IU
personalizada para tu aplicación
tener la ubicación correcta de la nota al pie, la marca de tiempo, el ícono de atribución y
un indicador de pila
si es necesario.
Después de la llamada
CardBuilder.getView()
:
usar
findViewById()
en el resultado para acceder a las vistas dentro de tu diseño incorporado. Del mismo modo, si
llamar
CardBuilder.getRemoteViews()
:
puedes manipular las vistas del diseño incorporado pasando sus ID directamente
en la
RemoteViews
método set.
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
Para obtener un ejemplo más detallado, consulta el repositorio Proyecto ApiDemo.
ALERT
El
CardBuilder.Layout.ALERT
contiene un ícono grande centrado con una
mensaje principal y nota al pie. Usa este diseño en una
Dialog
a
mostrar un mensaje informativo, una advertencia o un error importante en Glassware.
En el siguiente ejemplo, se muestra una implementación de AlertDialog
y se descarta el elemento
y abre la configuración de Wi-Fi cuando el usuario la toca:
- Crea una clase que extienda
Dialog
. - Crea la tarjeta usando
CardBuilder
con el diseñoCardBuilder.Layout.ALERT
y, luego, configura la vista de contenido con esta tarjeta. (Opcional) Crea un
GestureDetector
para controlar los gestos del usuario en esta tarjeta.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); } }
(Opcional) En tu actividad, implementa una
OnClickListener
para manejar cualquier flujo adicional cuando el usuario presiona. Para obtener más información iniciar actividades de configuración, como Wi-Fi, consulta Iniciando configuración.Llama al constructor
AlertDialog
para mostrar la tarjeta de alerta.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(); ... } }
Diseños XML
Aquí hay dos diseños de tarjetas básicos que puedes usar si la clase CardBuilder hace lo siguiente: que no satisfagan tus necesidades.
Diseño principal
Este diseño define el padding y el pie de página estándares de una tarjeta. Pon tu toque personal
vistas en el RelativeLayout
vacío.
![](https://developers.google.cn/static/glass/images/grids/main-template.png?hl=es-419)
<?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>
Diseño de la columna izquierda
Esto define una columna izquierda de 240 px y una columna derecha de 400 px en forma de dos RelativeLayout
.
en las que puedes ingresar tus vistas.
![](https://developers.google.cn/static/glass/images/grids/left-column-template.png?hl=es-419)
<?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>
Dimensiones estándar
Usa este archivo junto con los diseños anteriores o con tus propios diseños para
para que se adhiera al estilo estándar de Glass. Crear este archivo como
res/values/dimens.xml
en tu proyecto de 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>