Flutter NumberPicker -Pick Integer and Decimals


Flutter NumberPicker Tutorial and example.

In this tutorial we explore how we can pick numbers, both decimals and integers using an awesome library called numberpicker. We have several ways of doing this. First we can use numberpicker just within our page directly. The user can scroll through the numbers and pick. As the user scrolls through, the current scroll value is automatically set to a button.

Then the second way is to use a number picker dialog. We have two types of dialogs: integer number picker dialog and decimal number picker dialog. In the integer picker dialog a user can select whole numbers only. In the decimal picker dialog a user can select decimal numbers.

Demo

Here's the demo

Flutter NumberPicker

Flutter NumberPicker

Video Tutorial

Main things You Learn in This Tutorial

Here are the things you will learn in this tutorial.

(a). What is a NumberPicker

A numberpicker is a package that allows us select numbers. The library we use is capable of allowing us easily pick both integers and decimal numbers.

(b). Types of NumberPicker.

As we've said there are two types of dialogs:

  1. Integer NumberPicker Dialog - To pick whole numbers.
  2. Decimal NumberPicker Dialog - To pick floating point or double or decimal numbers.

In the example we have buttons capable of showing both types of the dialogs.

(c). Installing and Using NumberPicker

NumberPicker is a third part library allowing us to easily select numbers. We can specify the range and settings like number of decimal places and minimum and maximum value as well as the steps.

We can install it by adding in your pubspec.yaml the following under dependencies:

  numberpicker: ^0.1.6

Then you can use it by first importing it:

import 'package:numberpicker/numberpicker.dart';

(d). How to Build a Stateful Widget with NumberPickers

Well we will build a page as our StatefulWidget. A stateful widget is a widget that has mutable state. That state can change. And certainly our Home page will have a state that changes. As we pick numbers the page state will be changing. And in fact in realtime as we even scroll through our number pickers our page state will change. This will allow us to update our buttons in realtime.

To do that first we have to create our widget by extending the StatefulWidget class:

class Home extends StatefulWidget {..}

Then we will also have a State object, our _HomeState:

class _HomeState extends State<Home> {
}

Inside the _HomeState we will be maintaining several instance fields:

  int _currentIntValue = 10;
  double _currentDoubleValue = 3.0;
  NumberPicker integerNumberPicker;
  NumberPicker decimalNumberPicker;

You can see we have current integer as well as double values being maintained inside our state.

Then when the state of those fields changes, we will notify the framework. This then allows it to notify the listeners attached to it.

      if (value is int) {
        setState(() => _currentIntValue = value);
      } else {
        setState(() => _currentDoubleValue = value);
      }

You can see we use the setState() method to achieve that.

Common Concepts You can learn.

There are also several concepts a student can learn from this type of project. These include:

(a). How to do something when button is clicked

Well let's say we have a raised button. We want to show a dialog when it's clicked. Let's say we have a method responsible for showing that dialog called -_showIntegerDialog(). And we want to invoke.

here's how to do it:

              new RaisedButton(
                onPressed: () => _showIntegerDialog(),
                child: new Text("Current Int Value: $_currentIntValue"),
                color: Colors.lightBlue,
              ),

You can see we've set text to our button and that text is dynamic. This means it changes and the button has not static control of that text. We've also specified the color of the button using the color property.

pubspec.yaml

We add the numberpicker as a dependency here.

name: number_picker
description: A new Flutter project.

dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
  numberpicker: ^0.1.6

dev_dependencies:
  flutter_test:
    sdk: flutter

main.dart

Here's the main.dart file. It's our only file.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:numberpicker/numberpicker.dart';

//Our MyApp class
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Mr NumberPicker',
      theme: new ThemeData(
        primarySwatch: Colors.orange,
      ),
      home: new Home(title: 'NumberPicker'),
    );
  }
}
//Our Home stateful widget class
class Home extends StatefulWidget {
  //Our `Home` constructor
  //Receives a Key and title
  //A Key is an identifier for Widget
  Home({Key key, this.title}) : super(key: key);

  final String title;

  //Creates the mutable state for this widget at a given location in the tree.
  @override
  _HomeState createState() => new _HomeState();
}

//Our Home state. State is the logic and internal state for a StatefulWidget
class _HomeState extends State<Home> {
  int _currentIntValue = 10;
  double _currentDoubleValue = 3.0;
  NumberPicker integerNumberPicker;
  NumberPicker decimalNumberPicker;

  _handleValueChanged(num value) {
    if (value != null) {
      //`setState` will notify the framework that the internal state of this object has changed.
      if (value is int) {
        setState(() => _currentIntValue = value);
      } else {
        setState(() => _currentDoubleValue = value);
      }
    }
  }

  _handleValueChangedExternally(num value) {
    if (value != null) {
      if (value is int) {
        setState(() => _currentIntValue = value);
        integerNumberPicker.animateInt(value);
      } else {
        setState(() => _currentDoubleValue = value);
        decimalNumberPicker.animateDecimalAndInteger(value);
      }
    }
  }

  //this method will build our Home page. Here we will have several buttons
  //as well as integer and decimal numberpickers.
  @override
  Widget build(BuildContext context) {
    //build numberpicker for integer numbers
    integerNumberPicker = new NumberPicker.integer(
      initialValue: _currentIntValue,
      minValue: 0,
      maxValue: 100,
      step: 10,
      onChanged: _handleValueChanged,
    );
    //build number picker for decimal values
    decimalNumberPicker = new NumberPicker.decimal(
        initialValue: _currentDoubleValue,
        minValue: 1,
        maxValue: 5,
        decimalPlaces: 2,
        onChanged: _handleValueChanged);
    //scaffold the full homepage    
    return new Scaffold(
        appBar: new AppBar(
          title: new Text(widget.title),
        ),
        body: new Center(
          child: new Column(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              integerNumberPicker,
              new RaisedButton(
                onPressed: () => _showIntegerDialog(),
                child: new Text("Current Int Value: $_currentIntValue"),
                color: Colors.lightBlue,
              ),
              decimalNumberPicker,
              new RaisedButton(
                onPressed: () => _showDoubleDialog(),
                child: new Text("Current Decimal Value: $_currentDoubleValue"),
                color: Colors.lightGreen,

              ),
            ],
          ),
        ));
  }
  //show integer picker dialog
  //this method is asynchronous since we mark it with `async`.
  //So it will return a `Future` object, an object representing a delayed computation.
  Future _showIntegerDialog() async {
    await showDialog<int>(
      context: context,
      builder: (BuildContext context) {
        return new NumberPickerDialog.integer(
          minValue: 0,
          maxValue: 100,
          step: 10,
          initialIntegerValue: _currentIntValue,
        );
      },
    ).then(_handleValueChangedExternally);
  }
  //show decimal picker dialog
  //this method is asynchronous since we mark it with `async`.
  //So it will return a `Future` object, an object representing a delayed computation.
  Future _showDoubleDialog() async {
    await showDialog<double>(
      context: context,
      builder: (BuildContext context) {
        return new NumberPickerDialog.decimal(
          minValue: 1,
          maxValue: 5,
          decimalPlaces: 2,
          initialDoubleValue: _currentDoubleValue,
          title: new Text("Pick a decimal number"),
        );
      },
    ).then(_handleValueChangedExternally);
  }
}

void main() {
  runApp(new MyApp());
}

Downloading and Running

Just copy the main.dart file into your main.dart under the lib folder. Then add the numberpicker dependency.

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think


Previous Post Next Post