Android Material Dropdown: Selected dropdown item is presented like toString instead of defined View

Viewed 3018

I'm trying to use android material styling for components TextInputLayout with AutoCompleteTextView. I want the selected item is presented in the same way as in the dropdown list: image and text.

I tried with Spinner within TextInputLayout and Spinner and AutoCompleteTextView without TextInputLayout. All the combinations work but the first does not (material styling isn't applied for these combinations).

The selected item is presented as toString of the object that I use for my custom adapter.

What am I doing wrong?

P.S.: I'm using SVG drawables for the images.

main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/language_from"
        style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="32dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:hint="from"
        app:layout_constraintBottom_toTopOf="@+id/language_to"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <AutoCompleteTextView
            android:id="@+id/language_from_view"
            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
        android:id="@+id/language_to"
        style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:hint="to"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/language_from">

        <AutoCompleteTextView
            android:id="@+id/language_to_view"
            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
        android:id="@+id/searchInputLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        android:hint="label"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/language_to">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/searchInput"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </com.google.android.material.textfield.TextInputLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="412dp"
        android:layout_height="531dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/searchInputLayout">

    </androidx.recyclerview.widget.RecyclerView>

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val languageList = createLanguages()
        val adapter = LanguageAdapter(this, languageList)

        val languageFromDropdown = findViewById<AutoCompleteTextView>(R.id.language_from_view)
        val languageToDropdown = findViewById<AutoCompleteTextView>(R.id.language_to_view)

        languageFromDropdown.setAdapter(adapter)
        languageToDropdown.setAdapter(adapter)
    }

    private fun createLanguages(): List<LanguageDropdownItem>
            = listOf(LanguageDropdownItem(Language.POLISH, R.drawable.ic_polish_flag),
                     LanguageDropdownItem(Language.ENGLISH, R.drawable.ic_english_flag),
                     LanguageDropdownItem(Language.GERMAN, R.drawable.ic_german_flag),
                     LanguageDropdownItem(Language.FRENCH, R.drawable.ic_french_flag),
                     LanguageDropdownItem(Language.ITALIAN, R.drawable.ic_italian_flag),
                     LanguageDropdownItem(Language.SWISS, R.drawable.ic_swiss_flag))

}

language_dropdown_item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/flag_image"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="2dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_english_flag" />

    <TextView
        android:id="@+id/language_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/flag_image"
        app:layout_constraintTop_toTopOf="parent"
        android:ellipsize="end"
        android:maxLines="1"
        android:textAppearance="?attr/textAppearanceSubtitle1" />


</androidx.constraintlayout.widget.ConstraintLayout>

LanguageDropdownItem.kt

data class LanguageDropdownItem(val language: Language, val drawableFlag: Int)

LanguageAdapter.kt

class LanguageAdapter(val mContext: Context,
                      val mLanguages: List<LanguageDropdownItem>)
    : ArrayAdapter<LanguageDropdownItem>(mContext, 0, mLanguages) {

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        var dropdownItemView = convertView

        if (dropdownItemView == null)
            dropdownItemView = LayoutInflater.from(mContext)
                                .inflate(R.layout.language_dropdown_item, parent,false)

        val language = mLanguages[position]

        val flagImage: ImageView = dropdownItemView!!.findViewById(R.id.flag_image)
        flagImage.setImageResource(language.drawableFlag)

        val langTextView: TextView = dropdownItemView.findViewById(R.id.language_name)
        langTextView.text = language.language.name

        return dropdownItemView
    }
}

And Language is enum class with language names.

screenshot of my dropdown and selected result

2 Answers

If you would override toString() function of your LanguageDropdownItem, you will achieve what you want...

Note: I have solved my problem like this.

data class LanguageDropdownItem(val language: Language, val drawableFlag: Int) {
    override fun toString(): String {
        TODO()
    }
}

You can try like this in Kotlin by overriding tostring in your data class

data class LanguageDropdownItem(
  val language: Language,
  val drawableFlag: Int
){
    override fun toString(): String {
        //return "$language"
    }
}
Related