AutoCompleteTextViewをSpinnerとして使うには
2022/04/05
TextInputLayoutでドロップダウンメニューを使いたい場合はSpinnerが使えないのでAutoCompleteTextViewをカスタムしてみました。
DropDownNonFilter
フィルタリングせずに常時表示させるためだけのフィルター
class DropDownNonFilter : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults = FilterResults()
.also { results ->
// 常にリストがあることが分かれば良い
results.count = 1
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
}
}
DropDownArrayAdapter
リストの増減は不要なので、フィルターをセットするだけ
class DropDownArrayAdapter(context: Context, resource: Int, items: List<String>) : ArrayAdapter<String>(context, resource, items) {
override fun getFilter(): Filter = DropDownNonFilter()
}
DropDownTextView
class DropDownTextView(context: Context, attrs: AttributeSet) : AppCompatAutoCompleteTextView(context, attrs) {
private var isDropDownShowing: Boolean = false
// 選択肢が多くてスクロールする場合は、この行が一番上に表示される
// チェック状態にしておくには、アダプタをカスタムしないと無理だと思う
var selectionPosition: Int = 0
init {
// 入力を防止
inputType = InputType.TYPE_NULL
// 画面タッチでフォーカスを残さない
isFocusableInTouchMode = false
setOnTouchListener { _, ev ->
when (ev.action) {
MotionEvent.ACTION_DOWN -> showDropDown()
}
false
}
setOnDismissListener {
// ダブルクリックでは開き直さずに閉じたままにしておく
postDelayed({
isDropDownShowing = false
}, 10)
}
}
override fun showDropDown() {
if (!isDropDownShowing) {
super.showDropDown()
listSelection = selectionPosition
isDropDownShowing = true
}
}
// クリックされたら常時表示
override fun enoughToFilter(): Boolean = true
}
使ってみる
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val items = listOf("海", "山", "川")
val adapter = DropDownArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, items)
dropDownTextView.setAdapter(adapter)
dropDownTextView.setText("川")
dropDownTextView.selectionPosition = 2
}
補足
Spinnerの場合は、アダプタのメソッドでアイコン表示に変えられますが、AutoCompleteTextViewの場合は、EditTextとリスト部分で別々に対応しないといけないです。リストに選択状態のisCheckedを反映させたい場合も少々面倒です。Spinnerは便利ですね。