前編では、状態管理の仕組みを導入し、数値と演算子を保持する方法について学びました。後編では、ボタンタップ時の処理、計算ロジックの実装、そして状態の更新とUIへの反映について説明します。
3. ボタンタップ時の処理
まず、ボタンがタップされたときの処理を実装しましょう。CalculatorButton
ウィジェットの onPressed
プロパティに、ボタンの種類に応じた処理を記述します。
dart
CalculatorButton(
text: '7',
onPressed: () => _onNumberPressed('7'),
),
数値ボタンの場合は、_onNumberPressed
メソッドを呼び出し、引数としてボタンのテキストを渡します。演算子ボタンの場合は、_onOperatorPressed
メソッドを呼び出します。イコールボタンの場合は、_onEqualsPressed
メソッドを呼び出します。クリアボタンの場合は、_onClearPressed
メソッドを呼び出します。
_CalculatorState
クラスに、これらのメソッドを追加しましょう。
dart
class _CalculatorState extends State<Calculator> {
// ... 省略 ...
void _onNumberPressed(String number) {
setState(() {
if (_currentValue == 0) {
_currentValue = double.tryParse(number);
} else {
_currentValue = double.tryParse('$_currentValue$number');
}
_display = '$_currentValue';
});
}
void _onOperatorPressed(String operator) {
setState(() {
_previousValue = _currentValue;
_currentValue = 0;
_operator = operator;
_display = '$_previousValue $_operator';
});
}
void _onEqualsPressed() {
setState(() {
if (_previousValue != null && _operator != null) {
switch (_operator) {
case '+':
_currentValue = _previousValue! + _currentValue!;
break;
case '-':
_currentValue = _previousValue! - _currentValue!;
break;
case 'x':
_currentValue = _previousValue! * _currentValue!;
break;
case '/':
if (_currentValue == 0) {
_currentValue = null;
_display = 'Error';
return;
}
_currentValue = _previousValue! / _currentValue!;
break;
}
_display = '$_currentValue';
_previousValue = null;
_operator = null;
}
});
}
void _onClearPressed() {
setState(() {
_currentValue = 0;
_previousValue = null;
_operator = null;
_display = '0';
});
}
// ... 省略 ...
}
各メソッドでは、setState
を呼び出して状態を更新し、UIを再描画しています。
_onNumberPressed
メソッドでは、数値ボタンが押されたときの処理を記述します。現在の値が0の場合は、押された数値に置き換えます。それ以外の場合は、現在の値の後ろに押された数値を追加します。そして_display
に現在の値を代入します。
_onOperatorPressed
メソッドでは、演算子ボタンが押されたときの処理を記述します。現在の値を _previousValue
に保存し、_currentValue
を0にリセットします。選択された演算子を _operator
に保存します。そして_display
に前回の値と演算子を代入します。
_onEqualsPressed
メソッドでは、イコールボタンが押されたときの処理を記述します。_previousValue
と _operator
がnullでないことを確認し、_operator
の値に応じて計算を実行します。計算結果を _currentValue
に保存し、_display
に表示します。_previousValue
と _operator
をnullにリセットします。
_onClearPressed
メソッドでは、クリアボタンが押されたときの処理を記述します。すべての状態変数を初期値にリセットします。
4. 計算ロジックの実装
_onEqualsPressed
メソッドで、簡単な四則演算を実装しました。ただし、この実装にはまだ改善の余地があります。例えば、連続して演算子ボタンが押された場合や、0で除算しようとした場合の処理が不十分です。
これらの問題を解決するために、計算ロジックを改良しましょう。
dart
void _onEqualsPressed() {
setState(() {
if (_previousValue != null && _operator != null && _currentValue != null) {
double result = _calculate(_previousValue!, _currentValue!, _operator!);
if (result.isFinite) {
_currentValue = result;
_display = '$_currentValue';
} else {
_currentValue = null;
_display = 'Error';
}
_previousValue = null;
_operator = null;
}
});
}
double _calculate(double previousValue, double currentValue, String operator) {
switch (operator) {
case '+':
return previousValue + currentValue;
case '-':
return previousValue - currentValue;
case 'x':
return previousValue * currentValue;
case '/':
if (currentValue == 0) {
return double.infinity;
}
return previousValue / currentValue;
default:
return currentValue;
}
}
_calculate
という新しいメソッドを追加し、実際の計算処理をこのメソッドに移動しました。_onEqualsPressed
メソッドでは、_calculate
メソッドを呼び出し、計算結果を取得します。計算結果が有限値(isFinite
)の場合は、_currentValue
と _display
を更新します。無限大やNaNの場合は、エラーを表示します。
_calculate
メソッドでは、switch
文を使って演算子に応じた計算を実行します。0で除算しようとした場合は、無限大(double.infinity
)を返します。
5. 状態更新とUIへの反映
最後に、状態の更新をUIに反映させましょう。_CalculatorState
クラスの build
メソッドで、_display
変数の値を Text
ウィジェットに表示します。
dart
class _CalculatorState extends State<Calculator> {
// ... 省略 ...
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
// 結果表示エリア
Expanded(
child: Container(
color: Colors.blueGrey,
alignment: Alignment.bottomRight,
padding: const EdgeInsets.all(16.0),
child: Text(
_display, // _display 変数の値を表示
style: const TextStyle(
fontSize: 48.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
),
// ボタンエリア
// ... 省略 ...
],
),
);
}
}
_display
変数の値が Text
ウィジェットに表示されるようになりました。
また、CalculatorButton
ウィジェットの onPressed
プロパティを修正し、ボタンの種類に応じたメソッドを呼び出すようにします。
dart
CalculatorButton(
text: '7',
onPressed: () => _onNumberPressed('7'),
),
CalculatorButton(
text: '8',
onPressed: () => _onNumberPressed('8'),
),
// ... 省略 ...
CalculatorButton(
text: '/',
onPressed: () => _onOperatorPressed('/'),
),
CalculatorButton(
text: 'x',
onPressed: () => _onOperatorPressed('x'),
),
// ... 省略 ...
CalculatorButton(
text: '=',
flex: 2,
onPressed: () => _onEqualsPressed(),
color: Colors.orange,
),
CalculatorButton(
text: 'C',
onPressed: () => _onClearPressed(),
),
これで、ボタンをタップしたときの処理が実装され、状態の更新がUIに反映されるようになりました。