AutoCompleteTextView selección de elementos mediante programación

7 minutos de lectura

avatar de usuario
Hussein Yassine

Yo tengo un AutoCompleteTextView que está lleno de ciudades de una base de datos sqlite que llama a un AsyncTask al hacer clic en el elemento, recientemente agregué una opción para detectar mi ubicación usando el gps, por lo que el problema es que puedo detectar la ciudad (es decir, Beirut) y configurar el texto para el AutoCompleteTextView pero la cuestión es que el filtro desplegable se abre y muestra Beirut (lo cual es correcto), pero todavía necesito hacer clic en el elemento de la lista para invocar al oyente, cómo hacerlo mediante programación

Cómo:

  • Ingrese la actividad (HECHO)
  • Detectar ubicación (HECHO)
  • establecer el texto de la vista de texto (HECHO)
  • Mostrar lista desplegable de vista de texto (HECHO)
  • elegir el artículo que será devuelto, ya que solo devolverá una ciudad (NO HECHO)

avatar de usuario
JHowzer

Para ser claros, la solución de Tano es suficiente para responder a esta pregunta. Pero, en caso de que otros se encuentren con el mismo caso de uso que yo, aquí hay más antecedentes que pueden ayudarlo…

Me había encontrado con este problema específicamente al intentar hacer un no editable Menú desplegable Material expuesto y establezca su valor inicial mediante programación. La documentación para crear este tipo de “desplegable” se puede encontrar en la sección Menús Desplegables Expuestos aquílo que sugiere un mecanismo que utiliza TextInputLayout y AutocompleteTextView (incluso si no desea la funcionalidad de autocompletar).

Solución fallida 1:
A primera vista setListSelection() y getListSelection() parecía que podrían hacer el truco. Pero después de muchas pruebas, aprendí que pueden no ser suficientes porque solo funcionan cuando aparece la lista. isShowing(). Entonces, por ejemplo, si simplemente desea establecer la selección inicial sin tener que mostrar primero la ventana emergente de la lista, esto no funcionará.

Solución fallida 2:
Entonces lo intenté setText() que mostró el texto adecuado en mi cuadro de texto. ¡Hurra! ¡Pero espera! Cuando hice clic en la vista de texto, solo se mostró un subconjunto de opciones en la lista emergente por alguna razón. ¿Por qué fue eso? Lo más importante a tener en cuenta aquí es que, dado que se trata de un autocompletar vista de texto, por defecto filtros Opciones de salida basadas en el texto en la vista de texto. Es posible que esto no sea evidente, especialmente si solo usa este control para crear un selector desplegable simple no editable.

Solución:
Esto nos lleva a nuestra solución real (sugerida por Tano)… setText() con filter como false desactivará las capacidades de filtrado Y no cambiará el contenido de la ventana emergente de su lista.

autoCompleteTextView.setText(myText, false);

  • También estoy tratando de usar la vista de texto de autocompletar para crear un buen menú desplegable que se comporte como un Spinner (menos los molestos oyentes que disparan pero con el aspecto agradable que proporciona el textinputlayout). Las soluciones aquí funcionan para configurar el elemento seleccionado en función del texto, pero me gustaría tener todas las opciones disponibles cuando toca la función de autocompletar. En este momento todavía tendría que eliminar el texto para que aparezcan todos. ¿Algunas ideas? ¿O hay alguna manera de hacer que un Spinner se vea como el diseño de entrada de texto delineado?

    – JPM

    26 de julio de 2019 a las 2:02

  • Esta es una respuesta brillante y bien explicada. El único problema que tengo es que la opción de filtro requiere un nivel de API de 17

    – dave o grady

    3 de marzo de 2020 a las 0:41

  • @JPM, puede mostrar una lista desplegable en cualquier momento, consulte stackoverflow.com/a/26036902/2914140. Actualmente abre la lista completa (primera vez) incluso si se ha ingresado algún texto. Cuando edita un texto, filtra elementos. Tal vez stackoverflow.com/a/60791879/2914140 funciona, no lo verifiqué.

    – CoolMind

    2 de junio de 2020 a las 12:39


  • Pasé un par de horas en las soluciones fallidas mencionadas aquí, y ahora estoy así de cerca de un cambio de carrera después de desarrollar aplicaciones de Android durante 8 años.

    – SafaOrhan

    1 oct 2021 a las 15:25


avatar de usuario
tano

Estaba enfrentando un problema similar y esto resolvió mi problema. importante es llamar setText(<text>, <filter boolean>) para no filtrar con el texto dado establezca el segundo parámetro con false. El texto se obtendrá del adaptador desplegable.

Fragmento de solución:

automCompleteTextView.setText(automCompleteTextView.getAdapter().getItem(position).toString(), false);

  • ¡Gracias! Pienso, false es un valor predeterminado. Entonces, podemos usar autoCompleteTextView.setText(someText);.

    – CoolMind

    2 de junio de 2020 a las 13:01

  • Funciona perfectamente gracias!

    – DAVE SUCIO

    16 de enero a las 9:59

Una solución donde no necesita cambiar su nivel de API.

automCompleteTextView.setAdapter(adapter);        
// set default selection, filtering is active so all items is not visible in drop-down menu
automCompleteTextView.setText(automCompleteTextView.getAdapter().getItem(0).toString());
// change filtering for the adapter so all items can be visible in drop-down menu
adapter.getFilter().filter(null);

one-liner para el mismo trabajo pero requiere un nivel de API más alto

automCompleteTextView.setText(automCompleteTextView.getAdapter().getItem(0).toString(), false);

Me di cuenta después de profundizar en el código AutoCompleteTextView en el código fuente de Android:

fun AutoCompleteTextView.selectItem(text: String, position: Int = 0) {
  this.setText(text)
  this.showDropDown()
  this.setSelection(position)
  this.listSelection = position
  this.performCompletion()
}

autoComplete.setListSelection(position);

  • esto no selecciona el elemento para mí si la lista no se muestra

    – DAVE SUCIO

    16 de enero a las 9:57

he utilizado autoCompleteTextView.setText(myText, false); solución también, sin embargo, a veces fallaba. Quiero decir que estaba filtrando activamente los resultados, por lo que, cuando el usuario hace clic, solo había 1 elemento en el menú desplegable.

Además, también necesitaba esto para trabajar en objetos personalizados, y esta es mi solución:

binding.hourEditText.configureDropDownMenu(viewModel.hours) { it.hourString() }
    .subscribe {
        // Do whatever you need when on click.
    }
    .addTo(disposables)

fun <T> AutoCompleteTextView.configureDropDownMenu(list: List<T>, toString: ((T) -> String)? = null): Observable<T> {
    keyListener = null
    val textItems = toString?.let(list::map) ?: list.map { it.toString() }
    setAdapter(NonFilterArrayAdapter(context!!, android.R.layout.simple_spinner_dropdown_item, textItems))
    return itemClickEvents().map {
        list[it.position]
    }
}

private class NonFilterArrayAdapter<T>(context: Context, @LayoutRes resource: Int, objects: List<T>) : ArrayAdapter<T>(context, resource, objects) {

    override fun getFilter() = NonFilter()

    private class NonFilter : Filter() {
        override fun performFiltering(constraint: CharSequence?) = FilterResults()

        override fun publishResults(constraint: CharSequence?, results: FilterResults?) = Unit
    }
}

Nota: Esto también contiene un poco de Rx, pero se puede eliminar fácilmente.

  • esto no selecciona el elemento para mí si la lista no se muestra

    – DAVE SUCIO

    16 de enero a las 9:57

Intente agregar a continuación después de setText () en AutoCompleteTextview: –

autoCompleteTV.setSelection(position);

Actualizado:

Esto funcionará en Spinner y AutoCompleteTextView que tiene una función desplegable, pero no funcionará con EditText.

Aquí puede consultar los documentos para AbsSpinner en este enlace:
https://developer.android.com/reference/android/widget/AbsSpinner.html#setSelection(int)

  • @HusseinYassine Déjame revisar mi trabajo y regresaré con la solución.

    – Nitin Patel

    7 de julio de 2017 a las 6:35

  • setSelection es una forma abreviada de dónde colocar el cursor sin seleccionar un elemento en el Adaptador.

    – Chris Jenkins

    18 de agosto de 2019 a las 22:15

  • @Chris.Jenkins Para su aclaración, consulte este enlace desarrollador.android.com/reference/android/widget/… y aún no lo obtuve después de la inicialización, solo intente con una posición diferente.

    – Nitin Patel

    19 de agosto de 2019 a las 12:39

  • @NitinPatel Sí, eso es para un AbstractSpinner, AutoCompleteTextView no es eso. setSelection en una EditText establece la posición del cursor, no la selección de elementos en un control giratorio.

    – Chris Jenkins

    20 de agosto de 2019 a las 14:01


  • Esto puede provocar un bloqueo: ‘java.lang.IndexOutOfBoundsException: setSpan (43 … 43) termina más allá de la longitud 34’. Usar setListSelection en cambio.

    – CoolMind

    2 de junio de 2020 a las 13:44


¿Ha sido útil esta solución?