Android Adventures - Pickers
Written by Mike James   
Tuesday, 08 October 2013
Article Index
Android Adventures - Pickers
Date Picker
Number Picker

Number Picker

You know that the NumberPicker is going to be trouble when you notice that it is in the Expert section of the Toolbox!

In reality it is very easy to use and why it is in the Expert section, and not with the other Pickers, is difficult to work out.

To try it out start a new project called Number and accept all of the defaults. 

To use it all you have to do is select it an place it on the design surface. You will, like the other Pickers, see a version styled for the older APIs.

 

Numberold

 

If you run the app then you will see the NumberPicker styled for the latest API which in this case looks very odd because there is nothing loaded into the "spinner".

 

numberblank

 

The reason for this is that the NumberPicker is slightly more complicated than the other Pickers in that it allows you to set what the spinner part displays.

There are two distinct ways in which you can set the range that is displayed - as a pair of max min values, or as the values stored in an array.

For example, if you just want the NumberPicker to show 0 to 9 you might use:

NumberPicker np=
  (NumberPicker) findViewById(R.id.numberPicker);
np.setMaxValue(9);
np.setMinValue(0);

 

ten

 

If you don't want the number spinner to wrap around you can use

np.setWrapSelectorWheel(false);

If you want to give the user the choice of 0, 10, 20 and so on up to 90 you first have to initialize a string array of the correct size to these values. In this case the difference between MaxValue and MinValue properties +1  give the number of elements in the list. 

To create the array we need a simple for loop:


String[] values=new String[10];
for(int i=0;i<values.length;i++){
 values[i]=Integer.toString(i*10);
}

Once we have the array of values to display it can be assigned to the Picker using its setDisplayedValues method:

NumberPicker np=
   (NumberPicker) findViewById(R.id.numberPicker);
np.setMaxValue(values.length-1);
np.setMinValue(0);
np.setDisplayedValues(values);

 

tens

 

You may have noticed that the array used to specify the values is a String array. What this means is that the NumberPicker, despite its name, can allow the user to pick from a list of arbitrary strings that you can set.

For example:

String[] values=new String[3];
values[0]="mike";
values[1]="sue";
values[2]="harry";
np.setMaxValue(values.length-1);
np.setMinValue(0);
np.setDisplayedValues(values);

produces:

notanumber

 

When it comes to retrieving the data you can use the getValue method which return an integer which is either the value the user picked if you are not using a String array for the values or it is the index in the String array of the value the user picked. 

If you want to get a live update of the value the user selects you can use the OnValueChange event. The event handler

public void onValueChange(
 NumberPicker picker,
 int oldVal,
 int newVal)

provides you with the NumberPicker object that the event occurred on as picker and the index of the old and new values. The only problem is getting that value from the String array that defined the values displayed which is probably not accessible from the event handler. The solution is to use the NumberPicker's getDisplayedValues which returns a String array of values.

For example to transfer the value to a TextView you first have to define a Listener object which you can do easily with the help of Android Studio's autocomplete:

NumberPicker.OnValueChangeListener onValueChanged
 =new NumberPicker.OnValueChangeListener() {
 @Override
 public void onValueChange(
      NumberPicker picker,
      int oldVal,
      int newVal) {
  String[] values=picker.getDisplayedValues();
  TextView tv=
        (TextView) findViewById(R.id.textView);
  tv.setText(values[newVal]);
}
};

 

This uses the picker to get the array of displayed values which it then transfers to the TextView using the newVal as an index.

All you need to do to make this work is add the Listener to the NumberPicker:

 

np.setOnValueChangedListener(onValueChanged);

Now when your run the program the TextView is updated as soon as any changes are made.

 

dynamicnumbers

 

That's about all there is to basic use of the NumberPicker. 

For some tasks it is better to show the old style NumberPicker. Again all you need to do is make the standard change to values-v14/styles.xml and any other style XML files that are relevant. 

<style name="AppBaseTheme" 
              parent="android:Theme.Light">
<!-- API 14 theme customizations can go here. -->
</style>

If you do what you get is what you see in the Android Studio designer:

 

oldstylenumber

 

Multi-Digit Input

Finally if you want to create a multi-digit input - say hundreds, tens, units - then simply use three NumberPickers. This is more tricky than it first appears if you want to dynamically track the current value across more than one NumberPicker. 

For example, to build a three-digit input you first need to place three NumberPickers on the design surface with ids numberPicker1, numberPicker2 and numberPicker3.

 

threedigitdesign

You could initialize each of the NumberPickers in turn but it is instructive to use an array of NumberPickers to do the job:

NumberPicker[] nps=new NumberPicker[3];
nps[0]=
 (NumberPicker) findViewById(R.id.numberPicker1);
nps[1]=
 (NumberPicker) findViewById(R.id.numberPicker2);
nps[2]=
(NumberPicker) findViewById(R.id.numberPicker3);

Now we have an array of NumberPicker objects we can initialize them all in the same way using a for loop but first we need the array of values to be used:

String[] values=new String[10];
for(int i=0;i<values.length;i++){
 values[i]=Integer.toString(i);
}

As we are using 0 to 9 this could be done as an index without using an array but this makes the example more general.

Now we have the array of values we can initialize the NumberPickers:

for(int i=0;i<3;i++){
 nps[i].setMaxValue(values.length-1);
 nps[i].setMinValue(0);
 nps[i].setDisplayedValues(values);
 nps[i].setOnValueChangedListener(onValueChanged);
}

Notice that the same event handler is used for all of the NumberPickers. In some cases this is the way to do things in other it is better to have an event handler for each widget.

The next small problem is how to update the value displayed in a TextView when one of the NumberPickers changes its value.

Again the simplest solution for an example is to get the values from each of the NumberPickers using a for loop:

 

NumberPicker.OnValueChangeListener onValueChanged
       =new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(
    NumberPicker picker,
    int oldVal,
    int newVal) {
 NumberPicker[] nps=new NumberPicker[3];
 nps[0]=
  (NumberPicker) findViewById(R.id.numberPicker1);
 nps[1]=
  (NumberPicker) findViewById(R.id.numberPicker2);
 nps[2]=
  (NumberPicker) findViewById(R.id.numberPicker3);
 String temp="";
 for(int i=0;i<3;i++){
  String[] values=nps[i].getDisplayedValues();
  temp=values[nps[i].getValue()]+temp;
 }
 TextView tv=(TextView)findViewById(R.id.textView);
 tv.setText(temp);
}
};

 

In this case we don't use any of the event method's parameters we simply get the three NumberPickers and get their DisplayValues as a String array and the current value using the index returned by getValue.

The only tricky but is building up the string of digits to be displayed in temp. If you aren't sure what is going on try changing the line that sets temp to read:

 temp=temp+values[nps[i].getValue()];

In the jargon of math String concatenation is not commutative - in the jargon of programming it matters which end you stick something on to a String.

Of course as all three NumberPickers share the same set of values we really only need to getDisplayedValues once but this is more general. Also it is very obvious that part of the code are repeated and it would be better to refactor to create a function to get the three NumberPickers for example.

If you run the program you should be able to alter what is displayed in the TextView in a sensible three digit place value way:

 

threedigitpicker

 

The complete program, which you will find in the CodeBin, is:


package com.example.number;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.NumberPicker;
import android.widget.TextView;

public class MainActivity extends Activity {

 @Override

 protected void onCreate(Bundle savedInstanceState{
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 
 NumberPicker.OnValueChangeListener onValueChanged
   =new NumberPicker.OnValueChangeListener() {
 @Override
 public void onValueChange(
        NumberPicker picker,
        int oldVal,
        int newVal) {
  NumberPicker[] nps=new NumberPicker[3];
  nps[0]=
   (NumberPicker) findViewById(R.id.numberPicker1);
  nps[1]=
   (NumberPicker) findViewById(R.id.numberPicker2);
  nps[2]=
   (NumberPicker) findViewById(R.id.numberPicker3);
  String temp="";
  for(int i=0;i<3;i++){
   String[] values=nps[i].getDisplayedValues();
   temp=values[nps[i].getValue()]+temp;
  }
  TextView tv=
     (TextView) findViewById(R.id.textView);
  tv.setText(temp);
  }
 };

 
 String[] values=new String[10];
 for(int i=0;i<values.length;i++){
  values[i]=Integer.toString(i);
 }


 NumberPicker[] nps=new NumberPicker[3];
 nps[0]=
  (NumberPicker) findViewById(R.id.numberPicker1);
 nps[1]=
  (NumberPicker) findViewById(R.id.numberPicker2);
 nps[2]=
  (NumberPicker) findViewById(R.id.numberPicker3);
 for(int i=0;i<3;i++){
  nps[i].setMaxValue(values.length-1);
  nps[i].setMinValue(0);
  nps[i].setDisplayedValues(values);
  nps[i].setOnValueChangedListener(onValueChanged);
 }

}

 

Conclusion 

There is much more to say about the Pickers and how to customize them, but the methods explained here are the most common. If you need more help email me with a question. 

The biggest omission here is the use of the Pickers within a DialogFragment. This is a big topic that will be covered in a later chapter.

Meanwhile if you have any questions on what we've covered so far please let me know using the comments.

You can download the code for the programs from the CodeBin (note you have to register first).

 

Android Adventures With Android Studio

Contents

  1. Getting Started With Android Studio
  2. The Activity And The UI
  3. Building The UI and a Calculator App
  4. Lifecycle and State
  5. Basic Controls And Events
  6. Spinners
  7. Pickers
  8. UI Graphics A Deep Dive
  9. ListView And Adapters
  10. Introducing Fragments
  11. Fragments and XML
  12. Fragment And Activity Working Together
  13. Managing Fragments
  14. Custom dialogs using DialogFragment
  15. Dialog Classes In DialogFragment
  16. A NumberPicker DialogFragment Project
  17. ViewPager

If you are interested in creating custom template also see:

Custom Projects In Android Studio

Androidgears

 

 

 

 

To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter,FacebookGoogle+ or Linkedin,  or sign up for our weekly newsletter.

 

blog comments powered by Disqus



Last Updated ( Thursday, 20 November 2014 )
 
 

   
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.