Exposed dropdow menusの実装方法を紹介します。
目次
EditText(文字入力を要求するView)の入力候補(Exposed:手持ちの札を陳列する)を表示するメニューです。
※AutoCompleteTextViewはEditTextを継承しています。

Material Design ComponentsのText fieldsカテゴリの方が機能的に近いと思いますが、何故かMenusに属しています。
メニューの実装
Exposed drowdown menusの実装方法を示します。
サンプルの実装
入力候補を表示する機能はAutoCompleteTextViewが元から持っています。
AutoCompleteTextViewはメニュー表示に特化して開発されたクラスではありません。
Exposed dropdown menusは、このAutoCompleteTextViewをMaterial Designの指標に沿って装飾したものです。
メニューのレイアウト
メニューはTextInputLayoutの子ViewにAutoCompleteTextViewを配置した構成になります。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
...
tools:context=".MainActivity">
<!-- 左上のメニュー -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/txtInpLay"
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Item ?" ...>
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
<!-- 右下のメニュー -->
<com.google.android.material.textfield.TextInputLayout>
...
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
TextInputLayoutはLinearLayoutを継承していて、EditTextを一つだけ持つことが出来るコンテナタイプのViewです。※EditTextを二つ以上配置するとエラーになります。
このTextInputLayoutがMaterial Designの指標に沿った装飾を担っているラッパーです。
よって、Material Design ComponentsのMenusで紹介されているExposed dropdown menusは、必ず図のような構成になります。

メニューの部分はAutoCompleteTextViewが起動するListPopupWindowです。
ListPopupWindowはPopupWindow(パネルが浮き上がるような表示)とListView(アイテムを一覧表示)を組み合わせたものです。
メニューの組み込み
実装はListViewそのものです。
配列でメニューのアイテムを用意したので、ListAdapterにArrayAdapterを用いています。
メニューのアイテムをListAdapter経由で、AutoCompleteTextViewへ登録するだけです。
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="?attr/textAppearanceSubtitle1" />
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
val _items = arrayOf("Item 1", "Item 2", "Item 3")
val _adapter = ArrayAdapter(this, R.layout.menu_item, _items)
val _textInputlayout = findViewById<TextInputLayout>(R.id.txtInpLay)
val _editText = _textInputlayout.editText as? AutoCompleteTextView
_editText?.apply {
setAdapter(_adapter)
...
}
}
}
カスタマイズは他のListAdapter(Simple/CursorAdapterなど)を使ったり、アイテムのレイアウトを変更したり、ListViewと同じ方法が使えそうです。
サンプルの実行結果
図は上記で実装したExposed dropdown menusの実行結果です。

TextInputLayout(クリックに反応するのはAutoCompleteTextView)をクリックすると、その下に左上を起点としたドロップダウンメニューが開いて、アイテムが現れます。
ドロップダウンメニューが画面の外へ出てしまうときは、メニュー全体が表示できる位置へ移動されます。
アイテムのクリックイベント処理
AdapterView.OnItemClickListenerリスナーを実装し、AutoCompleteTextViewオブジェクトへ登録します。
アイテムのクリックが行われるとAdapterView.OnItemClickListenerにコールバックが返ってきます。
引数のpositionがクリックされたアイテムの位置を示しています。後は位置に基づいて処理を行います(サンプルはToastを発行)。
アイテムを一覧表示している部分はListViewなので、イベントの処理方法はListViewと全く同じです。
class MainActivity : AppCompatActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
val _items = arrayOf("Item 1", "Item 2", "Item 3")
val _adapter = ArrayAdapter(this, R.layout.menu_item, _items)
val _textInputlayout = findViewById<TextInputLayout>(R.id.txtInpLay)
val _editText = _textInputlayout.editText as? AutoCompleteTextView
_editText?.apply {
setAdapter(_adapter)
setOnItemClickListener { parent, view, position, id ->
val _item = parent.getItemAtPosition(position) as String
when(position) {
0 -> { // Item 1の処理
Toast.makeText(parent.context, _item, Toast.LENGTH_LONG)
.show() }
1 -> { // Item 2の処理
Toast.makeText(parent.context, _item, Toast.LENGTH_LONG)
.show() }
2 -> { // Item 3の処理
Toast.makeText(parent.context, _item, Toast.LENGTH_LONG)
.show() }
else -> {}
}
}
}
...
}
}
スタイルでデザインを変更
先にも述べましたが、TextInputLayoutがMaterial Designの指標に沿った装飾を担っているラッパーです。
TextInputLayoutのスタイルを変更すると、デザインが変えられるようになっています。
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/txtInpLay"
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Item ?" ...>
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
| スタイル名 Widget.MaterialComponents.TextInputLayout.*** | デザイン |
|---|---|
| FilledBox.ExposedDropdownMenu | ![]() |
| OutlinedBox.ExposedDropdownMenu | ![]() |
関連記事:


