制作安卓下拉菜单,TextInputLayout和AutoCompleteTextView简单实用

2,773 阅读4分钟

在安卓系统上创建和设计下拉菜单

Stelios Papamichail

Stelios Papamichail

关注

7月26日- 5分钟阅读

我最近不得不为我的应用程序实现一个定制的下拉菜单,我花了很长时间来弄清楚什么是风格,以及如何正确地实现它,以达到我想要的外观和感觉。所以,在这篇文章中,我将介绍如何使用TextInputLayout和AutoCompleteTextView来定制一个暴露的下拉菜单。我们将从这里开始。

略微定制的外露式下拉菜单

到这个。

最终的外露式下拉菜单

什么是暴露的下拉菜单?

外露式下拉菜单在选项列表的上方显示当前选择的菜单项。有些变化可以接受用户输入的信息。在安卓系统中,这个功能可以用一个TextInputLayout 和一个嵌套的AutocompleteTextView 来实现,它们都是安卓系统材料库的组成部分。让我们把这个库导入我们的项目中。

implementation ‘com.google.android.material:material:1.4.0’

我还将在本教程中使用ViewBinding ,所以请确保你在模块的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的Menus - Material Design文档。

赋予我们的下拉菜单一个更多的自定义外观

让我们从我们将用于下拉菜单背景的颜色开始。

<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的末端。我使用了免费的羽毛图标包中的下拉箭头。好了,现在我们有了所有的资源,让我们进一步设计我们的下拉菜单。

首先,我们要把TextInputLayout的background 设置为我们先前创建的drawable。

接下来,我们要通过改变各个角的radius ,使放置在TextInputLayout周围的盒子的角变圆(由于我们选择的样式),同时将boxStrokeWidthboxStrokeWidthFocused 设置为0dp ,因为我们不希望我们的下拉菜单上有任何轮廓。

此外,让我们使用endIconDrawable 属性添加我们的自定义下拉箭头图标,并使用endIconTint 将其染成与我们的风格相匹配。

现在我们已经完成了TextInputLayout的样式设计,所以让我们转到AutoCompleteTextView。在这里,我们要设置background="@null" ,这样它就不会和TextInputLayout的背景重叠了。

接下来,我们指定一个dropDownSelector drawable,在这种情况下,它将是我们先前创建的那个drawable。

DropDownSelector是一个可画的,当你点击一个项目时,它被用来突出显示该项目。

对于我的应用程序,我不希望有任何类似的东西是可见的,所以我只是把它设置为与我们的背景drawable相同。

继续下去,添加以下几行将简单地把文本限制在一行,以便一切看起来都是一致的,当文本太长时,省略号(...)将被添加在文本的末尾。

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")

很好,现在我们的下拉菜单已经填满了项目,我们需要定义一个自定义的drawable来作为下拉菜单的背景,因为现在将使用默认的白色背景。

使用一个自定义的下拉菜单背景绘图

再一次,我们将利用我们的filter_spinner_dropdown_bg.xml drawable。简单地在AutoCompleteTextView上调用setDropDownBackgroundDrawable() ,这就可以作为背景了。

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    }

本教程到此结束,你现在应该有一个功能齐全、外观漂亮的下拉菜单/旋转器了。如果你有任何建议、改进或意见,请在评论中告诉我,我会尽我所能将它们纳入。编码愉快!