Android Kotlin Custom Spinner DropDown With Image and Text

Android Spinner Provides a quick way to select one value from a set , Touching the spinner displays all available value from which user can select one .

In the previous tutorial we have seen
  1. Spinner as dropdown and dialog
  2. Styling Spinner Drop Down . 
In this tutorial We will see how to customize spinner drop down with image and text , lets see example


For loading data in spinner , I have kept json file inside asset folder and images inside drawable folder

JSON

Note : Here in this case  ("url")  field  in JSON is the name of image resource name kept in drawable folder ( as we are loading image from drawable into drop down layout )

File: app\src\main\assets\android_version.json
[
  {
    "name": "Cupcake",
    "url": "cupcake"
  },
  {
    "name": "Donut",
    "url": "donut"
  },
  {
    "name": "Eclairs",
    "url": "eclairs"
  },
  {
    "name": "Froyo",
    "url": "froyo"
  },
  {
    "name": "Gingerbread",
    "url": "gingerbread"
  },
  {
    "name": "Honeycomb",
    "url": "honeycomb"
  },

  {
    "name": "Icecream",
    "url": "icecream"
  },
  {
    "name": "Jellybean",
    "url": "jellybean"
  },

  {
    "name": "Kitkat",
    "url": "kitkat"
  },
  {
    "name": "Lolipop",
    "url": "lolipop"
  },

  {
    "name": "Marshmallow",
    "url": "marshmallow"
  },
  {
    "name": "Nougat",
    "url": "nougat"
  },
  {
    "name": "Oreo",
    "url": "oreo"
  },
  {
    "name": "Pie",
    "url": "pie"
  }
]

Image Resource

Folder : app\src\main\res\drawable


Main XML Layout


file : activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        android:orientation="vertical">

    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Custom Spinner With Text and Image"
              android:layout_marginTop="20dp"
              android:textSize="20sp"
              android:textStyle="bold"/>

    <androidx.appcompat.widget.AppCompatSpinner
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:id="@+id/spinner04"/>
    
</LinearLayout>

Model / Data Class


file : Model.kt
package com.tutorialsbuzz.customspinnerwithimagetext

data class Model(val name: String, val url: String) {
}


Custom DropDown Adapter


1.Drop Down Layout 

file: custom_spinner_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="horizontal"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:padding="8dp">

    <ImageView android:layout_width="40dp"
               android:layout_height="40dp"
               android:id="@+id/img"
               android:contentDescription="@string/app_name"/>

    <TextView android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:textSize="20sp"
              android:paddingStart="10dp"
              android:layout_gravity="center_vertical"
              android:id="@+id/text"/>

</LinearLayout>

2. DropDown Adapter

Create Custom Adapter this adapter will be used to set for spinner widget .

file: CustomDropDownAdapter
package com.tutorialsbuzz.customspinnerwithimagetext

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ImageView
import android.widget.TextView

class CustomDropDownAdapter(val context: Context, var dataSource: List<Model>) : 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.custom_spinner_item, parent, false)
            vh = ItemHolder(view)
            view?.tag = vh
        } else {
            view = convertView
            vh = view.tag as ItemHolder
        }
        vh.label.text = dataSource.get(position).name

        val id = context.resources.getIdentifier(dataSource.get(position).url, "drawable", context.packageName)
        vh.img.setBackgroundResource(id)

        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 label: TextView
        val img: ImageView

        init {
            label = row?.findViewById(R.id.text) as TextView
            img = row?.findViewById(R.id.img) as ImageView
        }
    }

}

MainActivity


  1. Create a koltin class MainActivity.kt and extend it to AppCompatActivity class .
  2. Override onCreate function and set the content of this MainActivity with above defined xml layout (activity_main.xml).
  3. Create a function readFromAsset (This method parse read json from asset folder parse and return List<Model>) .
  4. Create a instannce of CustomDropDownAdapter by passning context , List<Model> .
  5. Set the instannce of CustomDropDownAdapter to Spinner View.

file : MainActivity.kt
package com.tutorialsbuzz.customspinnerwithimagetext

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.gson.Gson
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

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

        val modelList: List<Model> = readFromAsset()

        val customDropDownAdapter = CustomDropDownAdapter(this, modelList)
        spinner04.adapter = customDropDownAdapter
    }

    private fun readFromAsset(): List<Model> {
        val file_name = "android_version.json"

        val bufferReader = application.assets.open(file_name).bufferedReader()

        val json_string = bufferReader.use {
            it.readText()
        }
        val gson = Gson()
        val modelList: List<Model> = gson.fromJson(json_string, Array<Model>::class.java).toList()
        return modelList
    }

}




Spinner Related
  1. Spinner DropDown With Image and Text
  2. Spinner as DropDown and Dialog
  3. Styling Spinner Drop Down

4 comments:

Luiz Emir said...

e como seria se eu pegasse de uma lista pronto no viewModel

Wisungyo said...

how can I show item selected on Toast with this code ??

Kapo™ said...

Have error: spinner04 must not be null

capital inicial said...

@Kapo, you need to initialize a variable with this element, i am using viewBinding but you can do using findViewById

Post a Comment