DZone
Web Dev Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Web Dev Zone > Custom Spinner for Android Application

Custom Spinner for Android Application

Learn how to create drop-downs (called spinners in Android parlance) using Kotlin for your Android applications.

Lachezar Balev user avatar by
Lachezar Balev
·
May. 02, 19 · Web Dev Zone · Tutorial
Like (1)
Save
Tweet
21.70K Views

Join the DZone community and get the full member experience.

Join For Free

Introduction

Spinners provide an easy way to select a single value from a set of values. Generally, it is very easy to create a standard spinner populated with choices represented by a TextView widget. Things get a bit more complicated when you want to show something fancy in the dropdown list. For example - images. In this article, we will build a spinner that is able to show an image next to text as in the screenshot below:

Image title

The final application is written in Kotlin and is of course available on GitHub. The free smileys are taken from Pixabay and lincensed under the Pixabay license.

First, we need to understand adapters and adapter views. Hopefully, the below figure sheds some light. 

Image title

As stated in the Android documentation, an adapter acts as a bridge between an AdapterView and the underlying data for that view. There are many standard adapter views. The Spinner is just one of them. Others are ListView, ExpandableListView, GridView, and more. What we are going to do is to:

  1. Create a data source for our spinner — we will use a simple list stuffed with data.

  2. Create an adapter for this data source which will extend ArrayAdapter.

  3. Attach our custom array adapter to a spinner.

Data Source

First of all, we will need a class that represents a single row in our spinner — Mood. This will be a simple Kotlin data class, a holder for an image resource id accompanied by text:

data class Mood(val image: Int, 
                val description: String)

That is pretty much it. We will use it soon when creating the list serving as a data source.

Adapter

This is the most important part of our custom spinner. The code is shown below:

class MoodArrayAdapter(ctx: Context,
                       moods: List<Mood>) :
    ArrayAdapter<Mood>(ctx, 0, moods) {

    override fun getView(position: Int, recycledView: View?, parent: ViewGroup): View {
        return this.createView(position, recycledView, parent)
    }

    override fun getDropDownView(position: Int, recycledView: View?, parent: ViewGroup): View {
        return this.createView(position, recycledView, parent)
    }

    private fun createView(position: Int, recycledView: View?, parent: ViewGroup): View {

        val mood = getItem(position)

        val view = recycledView ?: LayoutInflater.from(context).inflate(
            R.layout.demo_spinner,
            parent,
            false
        )

        view.moodImage.setImageResource(mood.image)
        view.moodText.text = mood.description

        return view
    }
}

Our adapter accepts a list with Mood instances. This list contains the actual data that will be shown in the spinner. We will use the parent constructor of ArrayAdapter that takes three arguments. The second is a resource id but we will pass 0 because this id is used only when the actual view is created. We will override these factory methods and take complete control of the view creation.

The idea behind the adapter views is that some of the views that show the data are reused instead of creating new ones. An example is when the user scrolls up and down in a list view. I highly recommend you watch this short video which clearly explains the theory behind view recycling. The difference between getView  and getDropDownView is that the later creates the views in the drop down list of the spinner as the name implies. In our case both of the views will be the same.

How do we create the actual view then? All of the action happens in our createView method. The position argument represents the position of the element that has to be visualized within our data array. getItem comes from the super class and returns the actual element from the moods list. If the recycled view is null this means that we need to inflate a new view, otherwise, we have to just populate the properties of the existing (scrap) view. The new view is inflated from the demo spinner layout which is shown below.

<android.support.constraint.ConstraintLayout ...>

    <ImageView
            android:id="@+id/moodImage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    <TextView
            android:id="@+id/moodText"
            android:layout_width="wrap_content"
            android:layout_height="20dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/moodImage"
            android:layout_marginStart="8dp" 
            app:layout_constraintBottom_toBottomOf="@+id/moodImage" 
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="8dp"/>
</android.support.constraint.ConstraintLayout>

There is absolutely nothing special in this layout, just an image and some text next to each other, that were quickly created with the designer in Android Studio.

Attaching the Adapter

Now we come the sweetest part — attaching the adapter to an existing spinner and enjoying the results. We have added a spinner into our main activity layout:

<android.support.constraint.ConstraintLayout  ...>

    <Spinner
            android:id="@+id/moodSpinner"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

Next we will hard code some moods and initialize our adapter with the below code:

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

        moodSpinner.adapter = MoodArrayAdapter(
            this,
            listOf(
                Mood(R.drawable.angry, "Angry"),
                Mood(R.drawable.happy, "Happy"),
                Mood(R.drawable.playful, "Playful"),
                Mood(R.drawable.wondering, "Wondering")
            )
        )

    }

After that, we are ready to run our application. The complete source is available here.

application Android (robot) Data (computing)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Which Backend Frameworks Are Impacting Web App Development Immensely?
  • Hard Things in Computer Science
  • No-Code/Low-Code Use Cases in the Enterprise
  • DZone's Article Submission Guidelines

Comments

Web Dev Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo