В этом документе рассматривается, как следовать стилю Glass и внедрять общие лучшие практики пользовательского интерфейса, которые могут оптимизировать взаимодействие с пользователем. Он охватывает следующие элементы пользовательского интерфейса:
Тема
Предлагаемая нами тема оформления Glass обладает следующими характеристиками:
- Отображает действия в полноэкранном режиме без панели действий.
- Применяет сплошной черный фон.
- Осветляет цвет для эффекта цветового края.
- Применяет белый цвет текста.
Ниже приведены рекомендуемые настройки темы для Glass:
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar"> <item name="android:windowBackground">@android:color/black</item> <item name="android:colorEdgeEffect">@android:color/white</item> <item name="android:textColor">@android:color/white</item> </style>
XML-макеты
Вот два основных варианта расположения карт, которые могут быть созданы с помощью ваших фрагментов:
Основная планировка
Этот макет определяет рекомендуемые стандартные отступы и нижний колонтитул для карточки. Разместите свои собственные элементы в пустом FrameLayout .

Вот пример XML-разметки:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/body_layout" android:layout_width="0dp" android:layout_height="0dp" android:layout_margin="@dimen/glass_card_margin" app:layout_constraintBottom_toTopOf="@id/footer" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <!-- Put your widgets inside this FrameLayout. --> </FrameLayout> <!-- The footer view will grow to fit as much content as possible while the timestamp view keeps its width. If the footer text is too long, it will be ellipsized with a 40dp margin between it and the timestamp. --> <TextView android:id="@+id/footer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/glass_card_margin" android:layout_marginEnd="@dimen/glass_card_margin" android:layout_marginBottom="@dimen/glass_card_margin" android:ellipsize="end" android:singleLine="true" android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/timestamp" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/timestamp" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/glass_card_margin" android:layout_marginBottom="@dimen/glass_card_margin" android:ellipsize="end" android:singleLine="true" android:textAlignment="viewEnd" android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Расположение в левой колонке
Этот макет определяет левую колонку шириной в одну треть и правую колонку шириной в две трети в виде двух классов FrameLayout , в которые вы можете поместить свои представления. Пример показан на следующем рисунке.

Вот пример XML-разметки:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/left_column" android:layout_width="0dp" android:layout_height="match_parent" android:background="#303030" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintWidth_percent=".333"> <!-- Put widgets for the left column inside this FrameLayout. --> </FrameLayout> <FrameLayout android:id="@+id/right_column" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="@dimen/glass_card_two_column_margin" android:layout_marginStart="@dimen/glass_card_two_column_margin" android:layout_marginBottom="@dimen/glass_card_two_column_margin" android:layout_marginEnd="@dimen/glass_card_margin" app:layout_constraintBottom_toTopOf="@id/footer" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/left_column" app:layout_constraintTop_toTopOf="parent"> <!-- Put widgets for the right column inside this FrameLayout. --> </FrameLayout> <!-- The footer view will grow to fit as much content as possible while the timestamp view keeps its width. If the footer text is too long, it will be ellipsized with a 40dp margin between it and the timestamp. --> <TextView android:id="@+id/footer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/glass_card_margin" android:layout_marginEnd="@dimen/glass_card_margin" android:layout_marginBottom="@dimen/glass_card_margin" android:ellipsize="end" android:singleLine="true" android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/timestamp" app:layout_constraintStart_toEndOf="@id/left_column" /> <TextView android:id="@+id/timestamp" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/glass_card_margin" android:layout_marginBottom="@dimen/glass_card_margin" android:ellipsize="end" android:singleLine="true" android:textAlignment="viewEnd" android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Стандартные размеры
Используйте следующие элементы в сочетании с предыдущими макетами или вашими собственными макетами, чтобы создать файл, соответствующий стандартному стилю Glass. Создайте этот файл как res/values/dimens.xml в вашем проекте 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">40dp</dimen> <!-- The recommended margin between the bottom of the card and the footer. --> <dimen name="glass_card_footer_margin">50dp</dimen> <!-- The recommended margin for the left column of the two-column card. --> <dimen name="glass_card_two_column_margin">30dp</dimen> </resources>
Меню
Мы рекомендуем использовать RecyclerView для создания меню. Они должны основываться на стандартном файле меню Android из ресурсов проекта Android Studio. Android позволяет переопределить стандартное создание меню и заменить его вашей реализацией. Для этого выполните следующие шаги:
- Создайте макет с помощью
RecyclerViewи установите его в качестве представления для вашейActivity. - Настройте
RecyclerViewи его адаптер на использование только что созданной коллекции пунктов меню. - Переопределите метод
onCreateOptionsMenu.- Расширьте свое меню и добавьте новый элемент в коллекцию для каждого пункта меню.
- Вызовите метод
notifyDataSetChangedадаптера.
Котлин
override fun onCreateOptionsMenu(menu: Menu): Boolean { val menuResource = intent .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE) if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) { menuInflater.inflate(menuResource, menu) for (i in 0 until menu.size()) { val menuItem = menu.getItem(i) menuItems.add( GlassMenuItem( menuItem.itemId, menuItem.icon, menuItem.title.toString() ) ) adapter.notifyDataSetChanged() } } return super.onCreateOptionsMenu(menu) }
Java
@Override public boolean onCreateOptionsMenu(Menu menu) { final int menuResource = getIntent() .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE); if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) { final MenuInflater inflater = getMenuInflater(); inflater.inflate(menuResource, menu); for (int i = 0; i < menu.size(); i++) { final MenuItem menuItem = menu.getItem(i); menuItems.add( new GlassMenuItem(menuItem.getItemId(), menuItem.getIcon(), menuItem.getTitle().toString())); adapter.notifyDataSetChanged(); } } return super.onCreateOptionsMenu(menu); }
- Используйте
OnScrollListenerвместе сLayoutManagerиSnapHelper, чтобы определить, какой вариант был выбран. - Для обработки события выбора пункта меню необходимо дождаться жеста
TAP. - Создайте
Intent, содержащий информацию о выбранном пункте меню. - Задайте результат для этого действия и завершите его.
- Вызовите
startActivityForResultиз фрагмента или активности, где вы хотите отобразить меню. Для этого используйте жестTAP. - Переопределите метод
onActivityResultв вызывающем фрагменте или активности, чтобы обработать выбранный пункт меню.
Руководящие принципы
Ниже приведён список рекомендаций по настройке макета меню:
- Размер текста:
64sp - Цвет фона:
#96000000 - Используйте иконки Material Design размером
64dpx64dp - Установите флаг темы
windowIsTranslucentвtrue
На следующем изображении представлен пример настраиваемого макета меню:

Для получения подробной информации о реализации ознакомьтесь с примером приложения Card .
Страницы с возможностью пролистывания
Стеклянный дисплей и сенсорная панель работают вместе, обеспечивая удобное отображение карточек с возможностью пролистывания. Вы можете создавать страницы с возможностью пролистывания в своем приложении, используя стандартный API Android ViewPager .
Для получения дополнительной информации о том, как использовать Android ViewPager для прокрутки карточек или экранов, посетите документацию по обучению работе со слайдами на экране .