Crear un selector Spinner personalizado en Android usando Kotlin


Apuntes para diseñar un selector de estilo spinner con un poco de personalización, para mostrar un selector de divisas donde aparece el código de la divisa, el nombre y el simbolo.

Layout

En la vista donde tiene que aparecer el selector

<androidx.appcompat.widget.AppCompatSpinner
    android:id="@+id/sp_currency"
    style="?android:attr/spinnerItemStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginEnd="16dp"
    android:layout_marginTop="16dp"
    />

Layout para la vista de cada elemento

<?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="72dp">

    <TextView
        android:id="@+id/tv_text_1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="14dp"
        android:layout_marginEnd="16dp"
        android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
        app:layout_constraintEnd_toStartOf="@+id/tv_symbol"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Line 1" />

    <TextView
        android:id="@+id/tv_text_2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:ellipsize="marquee"
        android:maxLines="1"
        android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
        app:layout_constraintEnd_toEndOf="@+id/tv_text_1"
        app:layout_constraintStart_toStartOf="@+id/tv_text_1"
        app:layout_constraintTop_toBottomOf="@+id/tv_text_1"
        tools:text="line 2" />

    <TextView
        android:id="@+id/tv_symbol"
        android:layout_width="40dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:gravity="center"
        android:textAppearance="@style/TextAppearance.Material3.BodySmall"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="€" />

</androidx.constraintlayout.widget.ConstraintLayout>

ArrayAdapter personalizado

data class CurrencyItem(val code: String, val displayName: String, val symbol: String)

class CustomDropDownAdapter(val context: Context, var dataSource: List<CurrencyItem>) : BaseAdapter() {

    private val inflater: LayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

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

        val view: View
        val vh: ItemHolder
        if (convertView == null) {
            view = inflater.inflate(R.layout.item_currency_row, parent, false)
            vh = ItemHolder(view)
            view?.tag = vh
        } else {
            view = convertView
            vh = view.tag as ItemHolder
        }

        val item = dataSource[position]
        vh.text1.text = item.code
        vh.text2.text = item.displayName
        vh.text3.text = item.symbol

        return view
    }

    override fun getItem(position: Int): Any? {
        return dataSource[position];
    }

    override fun getCount(): Int {
        return dataSource.size;
    }

    override fun getItemId(position: Int): Long {
        return position.toLong();
    }

    private class ItemHolder(row: View?) {
        val text1: TextView
        val text2: TextView
        val text3: TextView

        init {
            text1 = row?.findViewById(R.id.tv_text_1) as TextView
            text2 = row.findViewById(R.id.tv_text_2) as TextView
            text3 = row.findViewById(R.id.tv_symbol) as TextView
        }
    }

}

Uso y demostración

Obtener listado de las divisas, con su código, nombre y simbolo

object CurrencyDataSource {

    fun getCurrenciesAvailable(): List<CurrencyItem> {

        val currencyCodeList = arrayListOf(
            "USD",
            "CAD",
            "EUR",
            "AED",
            "AFN",
            "ALL",
            "AMD",
            "ARS",
            "AUD",
            "AZN",
            "BAM",
            "BDT",
            "BGN",
            "BHD",
            "BIF",
            "BND",
            "BOB",
            "BRL",
            "BWP",
            "BYN",
            "BZD",
            "CDF",
            "CHF",
            "CLP",
            "CNY",
            "COP",
            "CRC",
            "CVE",
            "CZK",
            "DJF",
            "DKK",
            "DOP",
            "DZD",
            "EEK",
            "EGP",
            "ERN",
            "ETB",
            "GBP",
            "GEL",
            "GHS",
            "GNF",
            "GTQ",
            "HKD",
            "HNL",
            "HRK",
            "HUF",
            "IDR",
            "ILS",
            "INR",
            "IQD",
            "IRR",
            "ISK",
            "JMD",
            "JOD",
            "JPY",
            "KES",
            "KHR",
            "KMF",
            "KRW",
            "KWD",
            "KZT",
            "LBP",
            "LKR",
            "LTL",
            "LVL",
            "LYD",
            "MAD",
            "MDL",
            "MGA",
            "MKD",
            "MMK",
            "MOP",
            "MUR",
            "MXN",
            "MYR",
            "MZN",
            "NAD",
            "NGN",
            "NIO",
            "NOK",
            "NPR",
            "NZD",
            "OMR",
            "PAB",
            "PEN",
            "PHP",
            "PKR",
            "PLN",
            "PYG",
            "QAR",
            "RON",
            "RSD",
            "RUB",
            "RWF",
            "SAR",
            "SDG",
            "SEK",
            "SGD",
            "SOS",
            "SYP",
            "THB",
            "TND",
            "TOP",
            "TRY",
            "TTD",
            "TWD",
            "TZS",
            "UAH",
            "UGX",
            "UYU",
            "UZS",
            "VEF",
            "VND",
            "XAF",
            "XOF",
            "YER",
            "ZAR",
            "ZMK",
            "ZWL",
            "USD",
            "CAD",
            "EUR",
            "AED",
            "AFN",
            "ALL",
            "AMD",
            "ARS",
            "AUD",
            "AZN",
            "BAM",
            "BDT",
            "BGN",
            "BHD",
            "BIF",
            "BND",
            "BOB",
            "BRL",
            "BWP",
            "BYN",
            "BZD",
            "CDF",
            "CHF",
            "CLP",
            "CNY",
            "COP",
            "CRC",
            "CVE",
            "CZK",
            "DJF",
            "DKK",
            "DOP",
            "DZD",
            "EEK",
            "EGP",
            "ERN",
            "ETB",
            "GBP",
            "GEL",
            "GHS",
            "GNF",
            "GTQ",
            "HKD",
            "HNL",
            "HRK",
            "HUF",
            "IDR",
            "ILS",
            "INR",
            "IQD",
            "IRR",
            "ISK",
            "JMD",
            "JOD",
            "JPY",
            "KES",
            "KHR",
            "KMF",
            "KRW",
            "KWD",
            "KZT",
            "LBP",
            "LKR",
            "LTL",
            "LVL",
            "LYD",
            "MAD",
            "MDL",
            "MGA",
            "MKD",
            "MMK",
            "MOP",
            "MUR",
            "MXN",
            "MYR",
            "MZN",
            "NAD",
            "NGN",
            "NIO",
            "NOK",
            "NPR",
            "NZD",
            "OMR",
            "PAB",
            "PEN",
            "PHP",
            "PKR",
            "PLN",
            "PYG",
            "QAR",
            "RON",
            "RSD",
            "RUB",
            "RWF",
            "SAR",
            "SDG",
            "SEK",
            "SGD",
            "SOS",
            "SYP",
            "THB",
            "TND",
            "TOP",
            "TRY",
            "TTD",
            "TWD",
            "TZS",
            "UAH",
            "UGX",
            "UYU",
            "UZS",
            "VEF",
            "VND",
            "XAF",
            "XOF",
            "YER",
            "ZAR",
            "ZMK",
            "ZWL"
        )

        val currencyAvailableList: MutableList<CurrencyItem> = arrayListOf()

        currencyCodeList.forEach { code ->
            Currency.getAvailableCurrencies().find { it.currencyCode.equals(code) }?.let {
                currencyAvailableList.add(CurrencyItem(it.currencyCode, it.displayName, it.symbol))
            }
        }

        return currencyAvailableList
    }

}

en la vista donde se mostrará el selector

val listCurrency = CurrencyDataSource.getCurrenciesAvailable()

val arrayAdapter = CustomDropDownAdapter(requireContext(), listCurrency)
binding.spCurrency.adapter = arrayAdapter

//set optional default value
val index = listCurrency.withIndex()
    .first { it.value.code == "EUR" }
    .index
binding.spCurrency.setSelection(index)
Anuncio publicitario

Publicado por Codelaby

Mobile DevDesigner

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

A %d blogueros les gusta esto: