0

I have an AutoCompleteTextView inside an AlertDialog (custom view). I have registered an onItemClick event.

When I type into the input, a dropdown of choices does appear. However, when I click one of the items, the onItemClick event handler never fires.

I want to know what's wrong with my code and why it won't fire the event handler.

I've tried tracing through the AutoCompleteTextView code and can't find where the code that triggers the event handlers even exists. I have confirmed the handler is registered, though.

I have looked at every example of ACTV I can find online. I have looked at so many SO posts about this and none have helped or been on point.

package com.foobar.weightlifting.ui

import android.app.AlertDialog
import android.app.Dialog
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.AutoCompleteTextView
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.MutableLiveData
import com.foobar.weightlifting.R
import kotlinx.android.synthetic.main.lift_selector.*

class LiftDialog : DialogFragment(), AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
    companion object {
        private const val TAG = "LiftDialog"
        private const val POSITIVE_LABEL = "Select"
        private const val NEGATIVE_LABEL = "Cancel"
    }
    private val model = Model(MutableLiveData())
    private lateinit var that: LiftDialog

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        that = this
        return activity?.let {
            val inflater = requireActivity().layoutInflater
            val binding : com.foobar.weightlifting.databinding.LiftSelectorBinding = DataBindingUtil.inflate(inflater, R.layout.lift_selector, null, false)
            binding.model = model
            val view = binding.root

            // Setup autocomplete search bar
            val liftChoices = resources.getStringArray(R.array.lift_list)
            val adapter = ArrayAdapter<String>(context, R.layout.lift_selector, liftChoices)
            val autocompleteView: AutoCompleteTextView = view.findViewById(R.id.lift_search_bar)
            autocompleteView.setAdapter(adapter)
//            autocompleteView.onItemSelectedListener = that
//            autocompleteView.onItemClickListener = that

            autocompleteView.setOnItemClickListener { parent, view, position, id ->
                Log.d(TAG, "info: $position $id")
            }

            val builder = AlertDialog.Builder(it)
            builder.apply {
                setTitle("Describe the lift")
                setView(view)
                setPositiveButton(POSITIVE_LABEL) { dialog, which ->
                    Log.d(TAG, "user pressed the $POSITIVE_LABEL button: $which ; model: ${model.searchText.value}")
                }
                setNegativeButton(NEGATIVE_LABEL) { dialog, which ->
                    Log.d(TAG, "user pressed the $NEGATIVE_LABEL button: $which")
                }
            }
            builder.create()
        } ?: throw IllegalStateException("Blah")
    }

    override fun onNothingSelected(parent: AdapterView<*>?) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    data class Model(val searchText: MutableLiveData<String>)
}

and the layout XML file

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
        xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="model"
                  type="com.foobar.weightlifting.ui.LiftDialog.Model"/>
    </data>
        <AutoCompleteTextView android:layout_width="wrap_content"
                              android:id="@+id/lift_search_bar"
                              android:text="@={model.searchText}"
                              android:hint="@string/select_lift_hint"
                              android:dropDownWidth="match_parent"
                              android:layout_height="wrap_content"/>
</layout>

If I put a breakpoint in onItemClick I expect it to break when I click on an item from the autocomplete dropdown. Instead, nothing happens but a lonely D/EGL_emulation: eglMakeCurrent: 0xea5462e0: ver 3 0 (tinfo 0xcf6cc040) logged.

I've tried to trace through the AutoCompleteTextView code but I can't even find where the onItemClick event handler I've registered is ever called. I have confirmed that the event handler is registered with the AutoCompleteTextView instance, though.

user1713450
  • 1,307
  • 7
  • 18
  • I'll try it once I have a chance to translate it to Kotlin and get it to compile. Dropping your code (although I think you just copy-pasted Google's sample code that I have already seen dozens of times) in and commenting my code out, it errors out when I try to open the dialog. Just FYI when you posted this, it was 2am my time. You didn't need to follow up five hours later wondering if I'd tried your code yet :) And now I have to take my kids to school, so give me some more time :) Thanks. – user1713450 May 14 '19 at 13:15
  • OK Just saw the `android.R.layout.simple_dropdown_item_1line` part, which I know I'd seen a bunch yesterday because all day yesterday for like five hours I just read sample code all over the internet puzzling why mine wasn't working. :P – user1713450 May 14 '19 at 13:19

2 Answers2

0

by default, android:clickable attribute value of TextView is false. you must make it clickable by putting this line in your xml:

android:clickable="true"

Edit: as you can find the details in this link

listeners will call in down order. you can set the OnFocusChangeListener of your view.

kAvEh
  • 534
  • 4
  • 15
  • 1
    When you register onItemClick it automatically becomes clickable="true" so this isn't the right answer: https://developer.android.com/reference/android/widget/AutoCompleteTextView I tried it anyway and the event still doesn't fire. – user1713450 May 14 '19 at 13:02
  • you are right. check the edit and I think it will help you. – kAvEh May 15 '19 at 05:59
0

When you create the adapter, the layout you reference is supposed to be a layout for an individual autosuggest item, not the layout that contains the ACTV.

So changing the line instantiating the adapter to:

val adapter = ArrayAdapter<String>(context, android.R.layout.simple_dropdown_item_1line, liftChoices)

fixes the issue. This uses a built-in Android sample dropdown layout template.

user1713450
  • 1,307
  • 7
  • 18