DZone
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
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • AI: Do You Trust It?
  • How To Create a Homescreen Widget in Android
  • Spring Boot Application With Spring REST and Spring Data MongoDB
  • Accelerate Innovation by Shifting Left FinOps: Part 4

Trending

  • AI’s Role in Everyday Development
  • Docker Base Images Demystified: A Practical Guide
  • A Developer's Guide to Mastering Agentic AI: From Theory to Practice
  • How Large Tech Companies Architect Resilient Systems for Millions of Users
  1. DZone
  2. Data Engineering
  3. Data
  4. 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.

By 
Lachezar Balev user avatar
Lachezar Balev
·
May. 02, 19 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
23.6K 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.

Related

  • AI: Do You Trust It?
  • How To Create a Homescreen Widget in Android
  • Spring Boot Application With Spring REST and Spring Data MongoDB
  • Accelerate Innovation by Shifting Left FinOps: Part 4

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

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

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!