Android NumberPicker customization and alternatives

Some of the android components are not as easy to customize as we would expect them to be. What is more, sometime they don’t work as expected, and we need to look for some workarounds to solve these issues. Here I will cover possible personalization on standard NumberPicker supplied with Android SDK, and also I will show some alternatives with more personalization possibilities.

android NumberPicker customization
Default Android NumberPicker
Fully customizable Android Numbericker - GoodPicker
Fully customizable Android Numbericker – GoodPicker

How to change font in Android NumberPicker

Changing font in android NumberPicker can’t be done programmatically, only through styles xml. To assign your own custom font, you need to put your font int res/font directory. Next, you need to provide it in field android:fontFamily in your style.

<style name="CustomNumberPicker">
        <item name="android:fontFamily">@font/raleway_black</item>
</style>

And at the end you need to add it as android:theme to your layout.

<NumberPicker
       android:id="@+id/numberPicker"
       android:theme="@style/CustomNumberPicker"
...
</NumberPicker>

How to change text color in an android NumberPicker

Unfortunately in NumberPicker you can’t set separate colors for selected item and not selected item. However, it is possible to set the text color in general. To achieve that all you need to do is set field android:textColorPrimary in your style.

<style name="CustomNumberPicker">
        ...
        <item name="android:textColorPrimary">@color/purple_500</item>
</style>

How to change color of selector lines in android NumberPicker

The field responsible for color of selector lines (the lines surrounding the selected item) is android:colorControlNormal. To make lines disappear, just set the color to transparent.

<style name="CustomNumberPicker">
        ...
        <item name="android:colorControlNormal">#ddaa00</item>
</style>

How to disable EditText in android NumberPicker

Sometimes EditText in NumberPicker is not that useful feature and causes more troubles than it is worth it, so you might want to disable it. To achieve that all you need to do is to block focusability of descendants with a field android:descendantsFocusability


<style name="CustomNumberPicker">
       ...
        <item name="android:descendantFocusability">blocksDescendants</item>
</style>

That is pretty much it for android NumberPicker customizability. Below you can see final effect.

android NumberPicker customization
Customized Android NumberPicker

Fully customizable android NumberPicker – a GoodPicker

In this library, you can customize pretty much everything you will need. It is rewritten completely from scratch, and it is continuously maintained, so new features and fixes are still being implemented, but it is already fully functional and production ready. Github page of library can be found here: https://github.com/Stonks-tech/GoodPicker.

Installation

Add repository in project level build.gradle

allprojects {
    repositories {
        maven {
            url "https://stonks.jfrog.io/artifactory/stonks-gradle-release"
        }
    }
} 

or if your gradle is set up to define repositories in settings.gradle:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven {
            url "https://stonks.jfrog.io/artifactory/stonks-gradle-release"
        }
    }
}

Add dependency to your module level build.gradle

implementation 'tech.stonks:goodpicker:0.9.0'

Fields available in xml

AttributeDescription
app:overlayColorColor of the overlay lines
android:textColorColor of the text, You might use selector with state_selected to specify text color for selected value
android:textSizeSize of the text
android:textFontWeightWeight of the text, will take effect only on API 28 or higher
android:fontFont of the text
app:visibleItemsNumber of visible items in the picker

Fields available programmatically

Drawable picker in android as an alternative to android NumberPicker
Drawable picker in android
FieldDescription
styleStyle of the picker, see GoodNumberPicker.Style. Basically it contains all the fields that are available in xml
onSelectedPositionChangedListener that will be called when selected position changes. By default, it will be called when user stops scrolling.
publishUpdatesOnlyOnAnimationEndIf set to trueonSelectedPositionChanged will be called only when animation ends. Otherwise, it will be called on every scroll event.
selectedPositionYou can set it to change selected position programmatically.
itemsList of items that will be displayed in the picker.
itemFormatterFormatter that will be used to transform items
pickerOverlayOverlay that will be drawn above picked values. By default it will display two lines
visibleItemsNumber of visible items in the picker
tintTint of the picker. It will be applied to all drawables in the picker. You can use selector with state_selected to specify tint for selected value.
sizeSize of the drawable item.

Formatting items individually

In a GoodPicker you can format each item individually based on its position. Below is example where selected item has different color. But this feature is not limited to selected item only, you can implement it in any imaginable way.

numberPicker.itemFormatter = { index, item ->
    item.apply {
        val color = if (index == numberPicker.selectedPosition) {
            Color.RED
        } else {
            Color.BLACK
        }

        styleChanged(
            style.modifyCustomStyle<TextStyle> {
                this.copy(
                    textColor = color
                )
            }
        )
    }
}
Different color for selected item in the android NumberPicker
Different color for selected item in the GoodPicker

Custom item implementation in android NumberPicker alternative

If current possibilities are not enough for you, you can still implement your own items. An item can be pretty much everything, only canvas is your limitation, so here I will show you how to implement your item based on DrawablePickerItem example.

The most important method in here is of course draw which is responsible for drawing the item, but also you will need to implement styleChange to properly react on appearance changes.

class DrawablePickerItem(val drawable: Drawable) : PickerItem {
    private var _style: GoodPickerStyle = GoodPickerStyle.default
    override val style: GoodPickerStyle
        get() = _style
    private val _drawableStyle: DrawableStyle
        get() {
            return _style.getCustomStyle() ?: throw IllegalStateException("No drawable style found")
        }

    override fun draw(canvas: Canvas, y: Float, width: Int, height: Int) {
        val style = _drawableStyle
        canvas.save()
        canvas.translate(
            (width - style.size) / 2f, //here we center drawable
            y + ((height - style.size) / 2f),
        )
        drawable.setTint(style.tint) //before drawing we apply style
        drawable.setBounds(0, 0, style.size, style.size)
        drawable.draw(canvas)
        canvas.restore()
    }

    override fun styleChanged(style: GoodPickerStyle) {
        _style = style //after assignment you might want to invalidate your field to update paint or other things
    }

    companion object {
        fun fromResource(context: Context, resId: Int): DrawablePickerItem {
            return DrawablePickerItem(
                ContextCompat.getDrawable(context, resId)!!
            )
        }
    }
}

Other than that you can also implement your own PickerOverlay which by default is two lines surrounding selected item, but it can be everything. Below is gif with example custom fading overlay.

Custom android NumberPicker overlay
Custom GoodPicker overlay

Summary

Some of android components have very poor customization possibilities. That is why I have started creating libraries to replace such components. NumberPicker is only the first of many. In future I am planning to reimplement CalendarView and TimePicker, if you wait on any of them just follow me on Twitter. Also if you would like to see some other component reimplemented, feel free to contact me also on twitter or through contact form.

Stonks Software House

We make mobile apps. Fast. And also blogging about app development.