In this tutorial, we’re gonna build a Flutter App that uses Radio Button to select between a number of options.
Contents
Overview
Flutter App
Our example is Currency Converter App that can convert USD to Euro, Pound or Yen:
To do this, we are going to add 3 Radio Buttons that allow users to select Currency they want to convert from USD.
Radio Button
When one radio button in a group is selected, the others are un-selected. This means only one option is accepted at the same time.
Radio Button itself does not maintain any state. Instead, when the state of the radio button changes, the widget calls the onChanged
callback.
=> listen for the onChanged
callback and rebuild the Radio Button with groupValue
to update state variables.
class _CurrencyState extends State<Currency> { // state variable double _result = 0.0; void _handleRadioValueChange(int value) { setState(() { _radioValue = value; switch (_radioValue) { case 0: _result = ... break; case 1: _result = ... break; case 2: _result = ... break; } }); } @override Widget build(BuildContext context) { return new Scaffold( ... children: <Widget>[ new Radio( value: 0, groupValue: _radioValue, onChanged: _handleRadioValueChange, ), new Radio( value: 1, groupValue: _radioValue, onChanged: _handleRadioValueChange, ), new Radio( value: 2, groupValue: _radioValue, onChanged: _handleRadioValueChange, ), ] ... } } |
Practice
Project Structure
Add Image to Project
Under Project folder level, create images directory, then add currencies.png (you will find this image in the Source Code below).
Open pubspec.yaml, add assets:
flutter: ... assets: - images/currencies.png |
Create a Custom StatefulWidget
Create new currency.dart file at lib/ui/ for Currency
class:
import 'package:flutter/material.dart'; class Currency extends StatefulWidget { @override State<StatefulWidget> createState() { return new _CurrencyState(); } } class _CurrencyState extends State<Currency> { final TextEditingController _currencyController = new TextEditingController(); int _radioValue = 0; static const EURO_MUL = 0.86; static const POUND_MUL = 0.75; static const YEN_MUL = 110.63; double _result = 0.0; String _textResult = ''; void _handleRadioValueChange(int value) { setState(() { _radioValue = value; switch (_radioValue) { case 0: _result = _currencyCalculate(_currencyController.text, EURO_MUL); if (_result > -1.0) { _textResult = '${_currencyController.text} USD = ${_result.toStringAsFixed(3)} Euro'; } else { _textResult = 'Cannot convert USD to Euro\nPlease check the Amount!'; } break; case 1: _result = _currencyCalculate(_currencyController.text, POUND_MUL); if (_result > -1.0) { _textResult = '${_currencyController.text} USD = ${_result.toStringAsFixed(3)} Pound'; } else { _textResult = 'Cannot convert USD to Pound\nPlease check the Amount!'; } break; case 2: _result = _currencyCalculate(_currencyController.text, YEN_MUL); if (_result > -1.0) { _textResult = '${_currencyController.text} USD = ${_result.toStringAsFixed(3)} Yen'; } else { _textResult = 'Cannot convert USD to Yen\nPlease check the Amount!'; } break; } }); } void _handleCurrencyAmountChange(String amount) { setState(() { switch (_radioValue) { case 0: _result = _currencyCalculate(amount, EURO_MUL); if (_result > -1.0) { _textResult = '$amount USD = ${_result.toStringAsFixed(3)} Euro'; } else { _textResult = 'Cannot convert USD to Euro\nPlease check the Amount!'; } break; case 1: _result = _currencyCalculate(amount, POUND_MUL); if (_result > -1.0) { _textResult = '$amount USD = ${_result.toStringAsFixed(3)} Pound'; } else { _textResult = 'Cannot convert USD to Pound\nPlease check the Amount!'; } break; case 2: _result = _currencyCalculate(amount, YEN_MUL); if (_result > -1.0) { _textResult = '$amount USD = ${_result.toStringAsFixed(3)} Yen'; } else { _textResult = 'Cannot convert USD to Yen\nPlease check the Amount!'; } break; } }); } @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text('Currency Converter'), centerTitle: true, backgroundColor: Colors.blue, ), body: new Container( alignment: Alignment.center, child: new ListView( padding: const EdgeInsets.all(25.0), children: <Widget>[ new Image.asset( 'images/currencies.png', height: 150.0, width: 150.0, ), new Container( margin: const EdgeInsets.all(3.0), alignment: Alignment.center, child: new Column( children: <Widget>[ new TextField( controller: _currencyController, keyboardType: TextInputType.number, decoration: new InputDecoration( labelText: 'Amount', hintText: 'in USD', icon: new Icon(Icons.account_balance), ), onChanged: _handleCurrencyAmountChange, ), new Padding(padding: new EdgeInsets.all(5.0)), new Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ new Radio( value: 0, groupValue: _radioValue, onChanged: _handleRadioValueChange, ), new Text('Euro'), new Radio( value: 1, groupValue: _radioValue, onChanged: _handleRadioValueChange, ), new Text('Pound'), new Radio( value: 2, groupValue: _radioValue, onChanged: _handleRadioValueChange, ), new Text('Yen'), ], ), new Padding(padding: new EdgeInsets.all(15.0)), new Text( _currencyController.text.isEmpty ? 'Please enter the Amount!' : _textResult, style: new TextStyle( color: Colors.blueAccent, fontSize: 20.0, ), ), ], ), ) ], )), ); } double _currencyCalculate(String amount, double multiplier) { double _amount = amount.isNotEmpty ? double.parse(amount) : 0.0; if (_amount.toString().isNotEmpty && _amount > 0) { return _amount * multiplier; } else { return -1.0; } } } |
– Radio Button onChanged
callback points to _handleRadioValueChange()
method.
– Inside _handleRadioValueChange()
, we use setState()
to set the Widget’s state, and _textResult
state variable will be updated to show the result.
– We create a TextEditingController
(_currencyController
) to get input Amount value (TextField
), and we also use onChanged
callback of TextField
class to update the result everytime the text changes.
Inflate and attach stateful widget to screen
main.dart
import 'package:flutter/material.dart'; import './ui/currency.dart'; void main() { runApp(new MaterialApp( title: 'JSA Currency Converter', home: new Currency(), )); } |
Source Code
Last updated on February 7, 2020.