Создание и стилизация раскрывающихся меню на Android
Недавно мне пришлось реализовать настраиваемое раскрывающееся меню для своего приложения, и мне потребовалось много времени, чтобы понять, что нужно стилизовать и как это делать правильно, чтобы добиться того внешнего вида, к которому я стремился. Итак, в этой статье я расскажу, как настроить раскрывающееся раскрывающееся меню с помощью TextInputLayout и AutoCompleteTextView. Мы собираемся уйти от этого:
к этому:
Что представляют собой раскрывающиеся меню?
Открытые раскрывающиеся меню отображают текущий выбранный пункт меню над списком параметров. Некоторые варианты могут принимать вводимые пользователем данные. В Android эту функцию можно реализовать с помощью TextInputLayout
вместе с вложенным AutocompleteTextView
, которые являются компонентами библиотеки материалов Android. Импортируем библиотеку в наш проект:
implementation ‘com.google.android.material:material:1.4.0’
Я также собираюсь использовать V iewBinding в этом руководстве, поэтому убедитесь, что вы включили его в build.gradle вашего модуля, добавив следующее:
android { ... buildFeatures { viewBinding true } }
Разработка базового макета
Начнем с объявления основного макета раскрывающегося меню материала.
<com.google.android.material.textfield.TextInputLayout android:id="@+id/dateFilterContainer" style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="@string/label"> <AutoCompleteTextView android:id="@+id/datesFilterSpinner" android:layout_width="match_parent" android:layout_height="match_parent" android:inputType="none" tools:text="All Time"" /> </com.google.android.material.textfield.TextInputLayout>
Здесь мы просто добавляем TextInputLayout
, который содержит AutoCompleteTextView
, который будет действовать как раскрывающийся список. Обратите внимание на строку inputType="none"
, поскольку она сообщает AutoCompleteTextView, что мы не планируем вводить какие-либо текстовые данные вручную. Это в сочетании с настраиваемым стилем, который мы назначаем TextInputLayout, позволит AutoCompleteTextView работать как счетчик при нажатии.
Чтобы узнать больше о различных доступных стилях и параметрах настройки, взгляните на документацию Google Меню - Дизайн материалов.
Придаем нашему раскрывающемуся списку более индивидуальный вид
Начнем с цвета, который мы будем использовать для фона раскрывающегося списка.
<color name="pastel_orange_light">#FBE8DF</color>
Затем мы собираемся создать новый filter_spinner_dropdown_bg.xml
рисованный объект и использовать следующий код, чтобы придать ему форму:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/pastel_orange_light" /> <corners android:radius="20dp" /> </shape>
Последнее, что нам понадобится, это значок раскрывающегося списка, который будет помещен в конец TextInputLayout. Я использовал стрелку вниз из бесплатного набора значков с перьями. Хорошо, теперь, когда у нас есть все ресурсы, давайте продолжим оформление раскрывающегося списка.
Прежде всего, мы собираемся установить background
нашего TextInputLayout в значение drawable, которое мы создали ранее.
Далее мы собираемся скруглить углы поля, расположенного вокруг TextInputLayout (из-за нашего выбранного стиля), изменив radius
различных углов, а также установив boxStrokeWidth
и boxStrokeWidthFocused
на 0dp
, поскольку мы не хотим ничего наброски в раскрывающемся списке.
Кроме того, давайте добавим наш настраиваемый значок стрелки раскрывающегося списка с помощью атрибута endIconDrawable
, а также подкрашиваем его в соответствии с нашим стилем с помощью endIconTint
.
Мы закончили стилизацию TextInputLayout, поэтому перейдем к AutoCompleteTextView. Здесь мы устанавливаем background="@null"
, чтобы он не перекрывал фон нашего TextInputLayout.
Затем мы указываем dropDownSelector
drawable, который в этом случае будет таким же, как и drawable, который мы создали ранее.
DropDownSelector - это элемент рисования, который используется для выделения элемента при щелчке по нему.
В моем приложении я не хотел, чтобы что-то подобное было видно, поэтому я просто установил его таким же, как и наш фон для рисования.
Продолжая, добавление следующих строк просто ограничит текст одной строкой, чтобы все выглядело согласованно, а многоточие (...
) будет добавлено в конце текста, когда он будет слишком длинным.
android:ellipsize="end" android:maxLines="1" android:singleLine="true"
Мы также собираемся добавить отступы сверху и снизу, поскольку по какой-то причине вложение AutoCompleteTextView в TextInputLayout заставляет его немного обрезаться до границ TextInputLayout.
Наконец, мы немного центрируем и стилизуем наш текст, и все. Ниже приведен окончательный код.
<com.google.android.material.textfield.TextInputLayout android:id="@+id/typesFilterContainer" style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu" android:layout_width="wrap_content" android:layout_height="40dp" android:background="@drawable/filter_spinner_dropdown_bg" app:boxBackgroundColor="@color/pastel_orange_light" app:boxCornerRadiusBottomEnd="20dp" app:boxCornerRadiusBottomStart="20dp" app:boxCornerRadiusTopEnd="20dp" app:boxCornerRadiusTopStart="20dp" app:boxStrokeWidth="0dp" app:boxStrokeWidthFocused="0dp" app:endIconDrawable="@drawable/ic_arrow_down" app:endIconTint="@color/pastel_orange_txt_highlight"> <AutoCompleteTextView android:id="@+id/typesFilter" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@null" android:fontFamily="@font/lato" android:dropDownSelector="@drawable/filter_spinner_dropdown_bg" android:ellipsize="end" android:inputType="none" android:maxLines="1" android:paddingTop="10dp" android:paddingBottom="10dp" android:singleLine="true" android:text="All Types" android:textAlignment="center" android:textColor="@color/pastel_orange_txt_highlight" tools:ignore="LabelFor" /> </com.google.android.material.textfield.TextInputLayout>
Теперь у вас должно получиться что-то вроде этого:
Давайте посмотрим, как мы можем заполнить раскрывающийся список элементами дальше!
Указание элементов раскрывающегося списка
Чтобы установить элементы раскрывающегося списка для нашего меню, нам нужно использовать ArrayAdapter<>()
и передать контекст, макет элемента и список элементов. В этом случае мы собираемся использовать предопределенный макет android.R.layout.simple_spinner_dropdown_item
, поскольку он покроет наши потребности на данный момент, но вы также можете использовать собственный макет и настроить его еще больше в пользовательском подклассе ArrayAdapter. Давайте посмотрим на код:
val adapter = ArrayAdapter(
requireContext(), android.R.layout.simple_spinner_dropdown_item, arraylistOf("All Types", "Assignments", "Exam", "Lab")
)
binding?.typesFilterSpinner?.setAdapter(adapter)
binding?.typesFilterSpinner?.setText("All Types")
Отлично, теперь, когда наше раскрывающееся меню заполнено элементами, нам нужно определить настраиваемый объект для рисования, который будет использоваться в качестве фона раскрывающегося списка, поскольку прямо сейчас будет использоваться белый по умолчанию.
Использование настраиваемого выпадающего фона с возможностью рисования
И снова мы воспользуемся нашим filter_spinner_dropdown_bg.xml
drawable. Просто вызовите setDropDownBackgroundDrawable()
в AutoCompleteTextView, и это будет для фона.
binding?.typesFilterSpinner.setDropDownBackgroundDrawable( ResourcesCompat.getDrawable( resources, R.drawable.filter_spinner_dropdown_bg, null ) )
Хорошо, мы наконец закончили со стилем нашего раскрывающегося списка. Теперь это должно выглядеть примерно так:
В нашей последней части мы увидим, как обрабатывать события щелчка по элементам!
Обработка событий щелчка по элементам
Чтобы получать уведомления при щелчке по раскрывающемуся элементу, мы собираемся просто определить наш собственный AdapterView.OnItemClickListener
и использовать его в нашем AutoCompleteTextView.
binding?.typesFilterSpinner.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id-> // do something with the available information }
На этом мы завершаем этот урок, теперь у вас должно быть полностью функциональное и красивое выпадающее меню / счетчик. Если у вас есть какие-либо предложения, улучшения или комментарии в целом, сообщите мне об этом в комментариях, и я постараюсь их учесть. Удачного кодирования!