クリックできる目次
はじめに
こんにちは。FlutterでUIStepperのような部品を利用したくなりましたが、
FlutterでいうStepperとは、アプリ画面内の操作説明などを段階的に表示するUI部品の事のようで、iOSのボタンを押して数字を上げ下げする部品とは違うようでした。
「Cupertino Stepper」で検索してもそれらしいものが無かったので作成してみました。
参考になれば嬉しいです。
Stepper
iOS
アプリ内の設定値などを「+」と「-」ボタンを押して数字を増やす、減らすUI部品
この記事で作成するUIは、こちらになります。
参考: https://developer.apple.com/documentation/swiftui/stepper
Flutter
アプリ内の説明などウォークスルー的に利用されるUI部品
参考: https://api.flutter.dev/flutter/material/Stepper-class.html
カスタム作成したもの
押し心地など、iOSのネイティブと比較すると若干の相違はありますが、デザイン等は寄せてみました。
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
/// iOSのようなStepper Widget Widget customStepper(BuildContext context, {double width = 94, double height = 32, required void Function(bool isIncrement) changeValue}) { return SizedBox( width: width, height: height, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: Color(0xffeeeeee), ), child: Row( children: [ Expanded( flex: 1, child: Stack( children: [ ElevatedButton( child: null, style: ElevatedButton.styleFrom( shadowColor: Colors.transparent, primary: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0), ), ), onPressed: () { changeValue(false); }, ), IgnorePointer( ignoring: true, child: Align( alignment: Alignment.center, child: Icon(Icons.remove, size: 24, color: Colors.black), ), ) ], ) ), SizedBox( width: 1.5, child: Container( margin: EdgeInsets.fromLTRB(0, 6, 0, 6), color: Color(0xffd6d6d6), ), ), Expanded( flex: 1, child: Stack( children: [ ElevatedButton( child: null, style: ElevatedButton.styleFrom( shadowColor: Colors.transparent, primary: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0), ), ), onPressed: () { changeValue(true); }, ), IgnorePointer( ignoring: true, child: Align( alignment: Alignment.center, child: Icon(Icons.add, size: 24, color: Colors.black), ), ) ], ) ), ], ), ), ); } |
使い方
普段Widgetを差し込んでいる好きな場所に対して、以下のように記述します。
関数の引数名などは、ご自由に変更してください。
1 2 3 4 5 6 7 8 9 |
child: Center( child: customStepper(context: context, changeValue: (isIncrement) { if (isIncrement) { // +ボタンが押されたとき } else { // -ボタンが押されたとき } }), ), |
実装について
ElevatedButton
の中にIcon
を設置するとボタンのマージンが設定されてしまい、
うまく中央に揃ってくれないことから、StackでIconとElevatedButtonを重ねることにしました。IgnorePointer
を利用することで、Stackで重ねたボタンにちゃんとアクションイベントが行くようになり、ボタンの反応が悪くなるのを防いでいます。
iOS標準UIStepper
のサイズは横幅: 94, 高さ: 32
だったので、デフォルトのサイズとしています。