How to use the NumericStepper component (Starling version) (Starling version)

The NumericStepper component displays a numeric value between a minimum and maximum. The value may be changed by pressing the increment or decrement buttons. If editing is enabled (typically not enabled on mobile), the value may be changed by typing a value into a text input.

Screenshot of a Feathers NumericStepper component
A NumericStepper component skinned with MetalWorksMobileTheme

The Basics

First, let's create a NumericStepper control, set up its range of values, and add it to the display list.

var stepper:NumericStepper = new NumericStepper();
stepper.minimum = 0;
stepper.maximum = 100;
stepper.value = 50;
this.addChild( stepper );

The value property indicates the current value of the stepper, while the minimum and maximum properties establish a range of possible values. We can further control the stepper's behavior with the step property:

stepper.step = 1;

The step property controls how the numeric stepper's value is rounded as the user interacts with it. If we set the stepper's step to 1, as we do above, the stepper will increment on whole numbers only, and it cannot have a value like 4.5, for instance.

Add a listener to the Event.CHANGE event to know when the value property changes:

stepper.addEventListener( Event.CHANGE, stepper_changeHandler );

The listener might look something like this:

function stepper_changeHandler( event:Event ):void
{
    var stepper:NumericStepper = NumericStepper( event.currentTarget );
    trace( "stepper.value changed:", stepper.value);
}

Skinning a NumericStepper

The skins for a NumericStepper control are divided into three parts. There are the increment and decrement buttons and the text input. There are a few different layout modes that control where the buttons are placed relative to the text input. For full details about what skin and style properties are available, see the NumericStepper API reference. We'll look at a few of the most common properties below.

Layout

The numeric stepper's layout can be customized to place the buttons in different locations. In the example below, we place the buttons on the right side of the text input, stacked vertically, like you see with many desktop numeric steppers using StepperButtonLayoutMode.RIGHT_SIDE_VERTICAL:

stepper.buttonLayoutMode = StepperButtonLayoutMode.RIGHT_SIDE_VERTICAL;

There are two additional options for buttonLayoutMode. You can use StepperButtonLayoutMode.SPLIT_HORIZONTAL to place the decrement button on the left side of the text input and the increment button button on the right side. Similarly, you can use StepperButtonLayoutMode.SPLIT_VERTICAL to place the increment button on top of the text input and the decrement button on the bottom.

A gap may be placed between the text input and any button positioned next to it:

stepper.textInputGap = 10;

Simply set the textInputGap property to adjust this spacing.

When the buttons are both placed on the same side of the text input, you can include a gap between them too:

stepper.buttonLayoutMode = StepperButtonLayoutMode.RIGHT_SIDE_VERTICAL;
stepper.buttonGap = 3;

If the buttons are on different sides of the text input, the buttonGap property is ignored.

Skinning the Decrement Button

This section only explains how to access the decrement button sub-component. Please read How to use the Button component for full details about the skinning properties that are available on Button components.

With a Theme

If you're creating a theme, you can target the NumericStepper.DEFAULT_CHILD_STYLE_NAME_DECREMENT_BUTTON style name.

getStyleProviderForClass( Button )
    .setFunctionForStyleName( NumericStepper.DEFAULT_CHILD_STYLE_NAME_DECREMENT_BUTTON, setNumericStepperDecrementButtonStyles );

The styling function might look like this:

private function setNumericStepperDecrementButtonStyles( button:Button ):void
{
    var skin:ImageSkin = new ImageSkin( upTexture );
    skin.setTextureForState( ButtonState.DOWN, downTexture );
    button.defaultSkin = skin;
    button.defaultIcon = newImage( decrementIconTexture );
}

You can override the default style name to use a different one in your theme, if you prefer:

stepper.customDecrementButtonStyleName = "custom-decrement-button";

You can set the function for the customDecrementButtonStyleName like this:

getStyleProviderForClass( Button )
    .setFunctionForStyleName( "custom-decrement-button", setNumericStepperCustomDecrementButtonStyles );

Without a Theme

If you are not using a theme, you can use decrementButtonFactory to provide skins for the numeric stepper's decrement button:

stepper.decrementButtonFactory = function():Button
{
    var button:Button = new Button();

    //skin the decrement button here, if not using a theme
    var skin:ImageSkin = new ImageSkin( upTexture );
    skin.setTextureForState( ButtonState.DOWN, downTexture );
    button.defaultSkin = skin;
    button.defaultIcon = newImage( decrementIconTexture );

    return button;
}

Skinning the Increment Button

This section only explains how to access the increment button sub-component. Please read How to use the Button component for full details about the skinning properties that are available on Button components.

The numeric stepper's increment button may be skinned similarly to the decrement button. The style name to use with themes is NumericStepper.DEFAULT_CHILD_STYLE_NAME_INCREMENT_BUTTON or you can customize the style name with customIncrementButtonStyleName. If you aren't using a theme, then you can use incrementButtonFactory.

If your decrement button and increment buttons don't have icons, you can use decrementButtonLabel and incrementButtonLabel to set the button labels:

stepper.decrementButtonLabel = "-";
stepper.incrementButtonLabel = "+";

Skinning the Text Input

This section only explains how to access the text input sub-component. Please read How to use the TextInput component for full details about the skinning properties that are available on TextInput components.

With a Theme

If you're creating a theme, you can target the NumericStepper.DEFAULT_CHILD_STYLE_NAME_TEXT_INPUT style name.

getStyleProviderForClass( TextInput )
    .setFunctionForStyleName( NumericStepper.DEFAULT_CHILD_STYLE_NAME_TEXT_INPUT, setNumericStepperTextInputStyles );

The styling function might look like this:

private function setNumericStepperTextInputStyles( input:TextInput ):void
{
    input.backgroundSkin = new Image( backgroundTexture );
    input.padding = 20;
    input.isEditable = false;
}

You can override the default style name to use a different one in your theme, if you prefer:

stepper.customTextInputStyleName = "custom-text-input";

You can set the function for the customTextInputStyleName like this:

getStyleProviderForClass( TextInput )
    .setFunctionForStyleName( "custom-text-input", setNumericStepperCustomTextInputStyles );

Without a Theme

If you are not using a theme, you can use textInputFactory provide skins for the numeric stepper's text input:

stepper.textInputFactory = function():TextInput
{
    var input:TextInput = new TextInput();

    //skin the text input here, if not using a theme
    input.backgroundSkin = new Image( backgroundTexture );
    input.padding = 20;
    input.isEditable = false;

    return input;
}

On mobile devices with touch screens, you should generally set isEditable on the numeric stepper's text input to false because editing the text may be frustrating or confusing for users. The hit area for the text input may be very small, and since it is positioned adjacent to the buttons, accuracy can be an issue. Moreover, on iOS, a clear button is displayed when a text input has focus, meaning that there may be very even less space to render the text when editing.

In this situation, it may be better to treat the text input as a label that simply displays the value.