Kartendesign

In diesem Dokument erfahren Sie, wie der Glass-Stil angewendet wird. und die gängigen Best Practices für die Benutzeroberfläche bei der Nutzung des GDK zu implementieren.

Glasdesign

Glass wendet ein Standarddesign auf Ihre Glassware an, sodass es mit der übrigen Benutzeroberfläche einheitlich bleibt. Die hat folgende Eigenschaften:

  • Verwendet die Roboto-Schriftart
  • Aktivitäten werden im Vollbildmodus ohne Statusleiste oder Aktionsleiste angezeigt.
  • Einfarbiger, schwarzer Hintergrund

Deklarieren Sie in Ihrem Android-Manifest kein Design, um das Glass-Design anzuwenden.

Wenn Sie einen benutzerdefinierten Stil für Teile Ihrer Glassware haben und das Standard-Glass-Design für alles andere verwenden möchten, Übernahme aus Theme.DeviceDefault mit dem parent-Attribut:

<resources>
    <style name="CustomTheme" parent="@android:style/Theme.DeviceDefault">
        <!-- Theme customization goes here. -->
    </style>
</resources>

Weitere Informationen finden Sie im Android-Entwicklerleitfaden unter Stile und Designs finden Sie weitere Informationen zum Erstellen von Designs.

Karten im Glasstil

Die CardBuilder erstellt korrekt formatierte Karten anhand einer Reihe von Eigenschaften. Layouts verwenden bereitgestellt von CardBuilder.Layout damit Ihre Inhalte wie andere Inhalte auf Google Glass.

Gehe so vor, wenn du CardBuilder verwenden möchtest:

  1. Erstellen Sie eine Instanz von CardBuilder und verwenden Sie dabei das gewünschte Layout aus CardBuilder.Layout
  2. Legen Sie Eigenschaften der Karte wie den Text, die Fußnote und den Zeitstempel fest.
  3. CardBuilder.getView() anrufen um die Karte in ein Android-Gerät View oder CardBuilder.getRemoteViews() in ein RemoteViews. -Objekt enthält.
  4. Verwende die View in deinen Aktivitäten, Layouts oder in CardScrollView oder verwenden Sie die RemoteViews in einem LiveCard.

Allgemeine UI-Funktionen

Viele der von CardBuilder bereitgestellten Layouts unterstützen die gängige Benutzeroberfläche. die nachfolgend beschriebenen Funktionen ausführen. Weitere Informationen finden Sie in der Dokumentation zu den einzelnen Layouts unter CardBuilder.Layout finden Sie eine Liste der Funktionen, die von den einzelnen Kartentypen unterstützt werden.

Attributionssymbol

Das Zuordnungssymbol ist ein optionales 36 × 36-Pixel-Symbol, das auf in der unteren rechten Ecke einer Karte und rechts neben dem Zeitstempel. Festlegen durch Aufrufen von CardBuilder.setAttributionIcon() um Ihre Anwendung zu identifizieren, insbesondere auf Live-Karten, damit Nutzer um die Quelle der Informationen auf der Karte zu sehen.

Stack-Anzeige

Der Stack-Indikator, gesteuert CardBuilder.showStackIndicator(), ist eine umfaltbare Ecke, die in der oberen rechten Ecke einer Karte angezeigt wird. Verwenden als ein visueller Indikator, dass Ihre Karte ein Set mit anderen Karten darstellt, die die Nutzenden direkt nutzen können.

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();

Layouts

Die folgenden Beispiele zeigen die Layouts, die mit der CardBuilder

TEXT und TEXT_FIXED

Die CardBuilder.Layout.TEXT Layout mit randlosem Text und einer optionalen Bildmosaik im Hintergrund. Die Textgröße wird dynamisch so angepasst, dass sie verfügbar ist. CardBuilder.Layout.TEXT_FIXED ist ähnlich, aber verkleinert den Text.

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 und COLUMNS_FIXED

Die CardBuilder.Layout.COLUMNS ein Bildmosaik oder Symbol auf der Seite der Karte und Text auf der rechten Seite. Die Textgröße wird dynamisch angepasst. an den verfügbaren Platz anpassen. Um eine feste Textgröße beizubehalten, verwenden Sie 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

Die CardBuilder.Layout.CAPTION Layout hat ein Bildmosaik im Hintergrund. und ein kurzer Untertiteltext am unteren Rand der Karte. Ein Symbol kann auch wird neben dem Untertitel platziert, um beispielsweise die Identität einer Person darzustellen die mit dem Inhalt der Karte verknüpft sind.

<ph type="x-smartling-placeholder">
</ph>
Abbildung 1: (Hintergrundbild nach photoeverywhere.co.uk, zugeschnitten)
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

Die CardBuilder.Layout.TITLE Layout hat ein Bildmosaik im Hintergrund. mit einem zentrierten Titel und einem optionalen Symbol unten auf der Karte. Dieses Layout wird häufig verwendet, um Kontakte zu repräsentieren oder Ziele zu teilen. Fußnote und Zeitstempel sind wird für dieses Layout nicht unterstützt.

View view = new CardBuilder(context, CardBuilder.Layout.TITLE)
    .setText("TITLE Card")
    .setIcon(R.drawable.ic_phone)
    .addImage(R.drawable.beach)
    .getView();

AUTHOR

Verwenden Sie die Methode CardBuilder.Layout.AUTHOR , um eine Nachricht oder Konversation anzuzeigen der Fokus auf dem Autor liegt. Im Hintergrund wird ein Bildmosaik unterstützt, ein Symbol, das als Avatar des Autors verwendet wird, sowie eine Überschrift und Zwischenüberschrift, identifizierende Informationen aufgelistet.

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();

Die CardBuilder.Layout.MENU das Layout eines Standard-Glass-Menüs. Es hat eine zentrierten Symbol, Titel und einer optionalen Fußnote. Dieses Layout verwenden für Bestätigungsbildschirmen (dem Wechsel von "Löschen" zu "Gelöscht", nachdem der Nutzer einen Menüpunkt auswählt. Wenn Sie eine echte Speisekarte benötigen, sollten Sie eine Standardoptionen-Menü.

View view = new CardBuilder(context, CardBuilder.Layout.MENU)
    .setText("MENU layout")
    .setIcon(R.drawable.ic_phone)
    .setFootnote("Optional menu description")
    .getView();

EMBED_INSIDE

Die CardBuilder.Layout.EMBED_INSIDE Layout bettet eine benutzerdefinierte Layout-XML-Datei Ihres eigenen Designs in das Standard-Glass-Format ein. Kartenvorlage. So können Sie eine benutzerdefinierte Benutzeroberfläche für Ihre Anwendung entwerfen, die korrekte Platzierung von Fußnote, Zeitstempel, Zuordnungssymbol und ob sie erforderlich sind.

Nach dem Anruf CardBuilder.getView(), nutzen findViewById() auf das Ergebnis, um auf die Ansichten innerhalb des eingebetteten Layouts zuzugreifen. Gleichermaßen sollten Sie, wenn Sie Anruf CardBuilder.getRemoteViews(), können Sie die Ansichten Ihres eingebetteten Layouts ändern, indem Sie deren IDs direkt übergeben. in die RemoteViews Setter-Methoden.

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

Ein detaillierteres Beispiel finden Sie im GitHub ApiDemo-Projekt verfügbar ist.

ALERT

Die CardBuilder.Layout.ALERT enthält ein großes zentriertes Symbol mit einem primäre Botschaft und Fußnote. Verwenden Sie dieses Layout in einem Dialog bis in Ihrer Glassware wichtige Informationen, Warnungen oder Fehler anzeigen.

Das folgende Beispiel zeigt eine Implementierung von AlertDialog und schließt die Karte und öffnet die WLAN-Einstellungen, wenn der Nutzer auf die Karte tippt:

  1. Erstellen Sie eine Klasse, die Dialog erweitert.
  2. Erstellen Sie die Karte mit CardBuilder mit dem Layout „CardBuilder.Layout.ALERT“ und legen Sie dann die Inhaltsansicht mit dieser Karte fest.
  3. Optional: Erstellen Sie einen GestureDetector für Nutzergesten auf dieser Karte.

    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);
        }
    }
    
  4. (Optional) Implementieren Sie in Ihrer Aktivität ein OnClickListener um zusätzliche Abläufe zu verarbeiten, wenn die Nutzenden darauf tippen. Weitere Informationen zu Einstellungen wie WLAN starten, sehen Sie Starteinstellungen:

  5. Rufen Sie den AlertDialog-Konstruktor auf, um die Benachrichtigungskarte aufzurufen.

    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-Layouts

Hier sind zwei grundlegende Kartenlayouts, die Sie verwenden können, wenn die CardBuilder-Klasse nicht Ihren Anforderungen entsprechen.

Hauptlayout

Mit diesem Layout wird der Standardabstand und die Fußzeile für eine Karte festgelegt. Eigenes Bild erstellen Ansichten in den leeren RelativeLayout.

<?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 der linken Spalte

Definiert eine 240 Pixel große linke und eine 400 px rechte Spalte in Form von zwei RelativeLayouts. in die Sie Ihre Ansichten einfließen lassen können.

<?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>

Standarddimensionen

Verwenden Sie diese Datei in Verbindung mit den vorherigen Layouts oder Ihren eigenen Layouts, um um dem Standard-Glass-Stil zu entsprechen. Diese Datei erstellen als res/values/dimens.xml in Ihrem Android-Projekt.

<?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>