Projekt karty

Z tego dokumentu dowiesz się, jak zachować zgodność ze stylem Glass i wdrażać typowe sprawdzone metody dotyczące interfejsu podczas korzystania z GDK.

Motyw szklany

Google Glass stosuje standardowy motyw, dzięki czemu zachowuje spójność z pozostałymi elementami 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 części oprogramowania Glassware i chcą ustawić domyślny motyw Glass dla całej reszty, odziedzicz po Theme.DeviceDefault za pomocą atrybutu parent:

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

Zobacz przewodnik dla programistów aplikacji na Androida na stronie Style i motywy .

Karty ze szkła

CardBuilder tworzy prawidłowo sformatowane karty z danym zestawem właściwości. Korzystanie z układów źródło: CardBuilder.Layout aby Twoje materiały wyglądały i wyglądały jak inne Szkło.

Aby użyć aplikacji CardBuilder:

  1. Utwórz instancję CardBuilder, zapewniając jej odpowiedni układ z: CardBuilder.Layout
  2. Ustaw właściwości karty, takie jak tekst, przypis i sygnatura czasowa.
  3. Zadzwoń pod numer CardBuilder.getView() aby przekonwertować kartę na Androida View lub CardBuilder.getRemoteViews() aby przekonwertować go na RemoteViews obiektu.
  4. Korzystaj z View w aktywnościach, układach i na CardScrollView lub skorzystaj z RemoteViews w LiveCard.

Wspólne funkcje interfejsu

Wiele układów oferowanych przez CardBuilder obsługuje wspólny interfejs funkcji opisanych poniżej. Dokumentację poszczególnych układów znajdziesz w CardBuilder.Layout , gdzie znajdziesz listę funkcji obsługiwanych przez poszczególne typy kart.

Ikona informacji

Ikona informacji to opcjonalna ikona o wymiarach 36 × 36 pikseli, widoczna na w prawym dolnym rogu karty i po prawej stronie sygnatury czasowej. Ustaw , dzwoniąc CardBuilder.setAttributionIcon() do identyfikacji aplikacji, szczególnie na aktywnych kartach, i sprawdzić źródło informacji na danej karcie.

Wskaźnik stosu

Wskaźnik stosu, kontrolowany przez CardBuilder.showStackIndicator() to zagięcie narożnika widoczne w prawym górnym rogu karty. Użyj tego jako: aby wskazać, że karta reprezentuje inne karty, których użytkownik może kliknąć reklamę.

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, które są dostępne przy użyciu CardBuilder

TEXTTEXT_FIXED

CardBuilder.Layout.TEXT Układ strony zawiera tekst na całym ekranie z opcjonalnym elementem mozaika obrazów w tle. Rozmiar tekstu dynamicznie się zmienia, by jak najlepiej go dopasować 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();

COLUMNSCOLUMNS_FIXED

CardBuilder.Layout.COLUMNS na zdjęciu może mieć mozaikę lub ikonę. po lewej stronie karty i tekstu po prawej. Rozmiar tekstu jest dynamicznie dostosowywany aby jak najlepiej pasowały do dostępnej przestrzeni. Aby utrzymać stały rozmiar tekstu, użyj 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 układ zawiera mozaikę w tle i krótki tekst napisów wyrównany u dołu karty. Można też użyć ikony umieszczone obok podpisu, aby reprezentować np. tożsamość osoby powiązane z treścią karty.

Rys. 1 (obraz tła: photoeverywhere.co.uk, przycięte)
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 układ zawiera mozaikę w tle z wyśrodkowanym tytułem i opcjonalną ikoną u dołu karty. Ten układ jest często używany do reprezentowania kontaktów lub udostępniania celów. Przypis i sygnatura czasowa są nie jest obsługiwane w tym układzie.

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

AUTHOR

Użyj CardBuilder.Layout.AUTHOR układ do wyświetlania wiadomości lub wątku w których kładzie się nacisk na autora. obsługuje mozaikę obrazów w tle, ikonę, która służy jako awatar autora, oraz nagłówek i podtytuł, listę danych identyfikacyjnych.

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

CardBuilder.Layout.MENU układ wygląda jak standardowe menu Google Glass. Zawiera wyśrodkowaną ikonę, tytuł i opcjonalny przypis. Użyj tego układu do: ekranów potwierdzenia (przejście z „Deletion” (usuwanie) na „Remove” (usunięcie) po (np. wybierz pozycję menu). Jeśli potrzebujesz prawdziwego menu, skorzystaj z 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

CardBuilder.Layout.EMBED_INSIDE układ zawiera kod XML własnego układu w standardowym Google Glass szablon karty. Pozwala to zaprojektować niestandardowy interfejs aplikacji, ma prawidłowe umieszczenie przypisu, sygnatury czasowej, ikony atrybucji i prawidłowego umieszczenia przypisu do karty; stosu wywołań w razie potrzeby.

Po nawiązaniu połączenia CardBuilder.getView() należy użyć funkcji findViewById() i uzyskać dostęp do widoków w umieszczonym układzie. Podobnie, jeśli zadzwoń CardBuilder.getRemoteViews() możesz manipulować widokami układu umieszczonego, przekazując ich identyfikatory bezpośrednio w sekcji RemoteViews metody ustawiania.

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 GitHubie Projekt Apigee.

ALERT

CardBuilder.Layout.ALERT układ zawiera dużą wyśrodkowaną ikonę z wiadomości głównej i przypisu. Użyj tego układu w Dialog do w Google Glassware pojawi się ważny komunikat informacyjny, ostrzeżenie lub błąd.

Poniższy przykład pokazuje implementację interfejsu AlertDialog i zamieszcza i otwiera ustawienia Wi-Fi, gdy użytkownik kliknie kartę:

  1. Utwórz zajęcia z rozszerzeniem Dialog.
  2. Utwórz kartę za pomocą elementu CardBuilder z układem CardBuilder.Layout.ALERT, a następnie ustaw widok treści za pomocą tej karty.
  3. (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);
        }
    }
    
  4. (Opcjonalnie) W aktywności zaimplementuj OnClickListener obsługi dodatkowych procesów, gdy użytkownik kliknie reklamę. Więcej informacji na temat: uruchamianie ustawień takich jak Wi-Fi, zobacz Ustawienia początkowe.

  5. 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 który nie odpowiada Twoim potrzebom.

Układ główny

Ten układ definiuje standardowe dopełnienie i stopkę karty. Dodaj własne widoków w pustym 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>

Układ lewej kolumny

Definiuje lewą kolumnę o długości 240 pikseli i prawą o 400 pikseli. Mają postać dwóch kolumn RelativeLayout. który możesz wykorzystać.

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

Użyj tego pliku w połączeniu z poprzednimi lub własnymi układami, aby są zgodne ze standardowym stylem Glass. Utwórz ten plik jako res/values/dimens.xml w 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>