88 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/material.dart';
 | |
| 
 | |
| class IntStepperField extends StatelessWidget {
 | |
|   final String label;
 | |
|   final TextEditingController controller;
 | |
|   final int min;
 | |
|   final int max;
 | |
| 
 | |
|   const IntStepperField({
 | |
|     super.key,
 | |
|     required this.label,
 | |
|     required this.controller,
 | |
|     this.min = 0,
 | |
|     this.max = 24,
 | |
|   });
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     int value = int.tryParse(controller.text) ?? 0;
 | |
|     return Column(
 | |
|       crossAxisAlignment: CrossAxisAlignment.center,
 | |
|       children: [
 | |
|         Padding(
 | |
|           padding: const EdgeInsets.only(bottom: 2.0),
 | |
|           child: Text(
 | |
|             label,
 | |
|             textAlign: TextAlign.center,
 | |
|             style: const TextStyle(
 | |
|                 fontSize: 13,
 | |
|                 color: Colors.black87,
 | |
|                 fontWeight: FontWeight.w500),
 | |
|           ),
 | |
|         ),
 | |
|         Row(
 | |
|           mainAxisSize: MainAxisSize.min,
 | |
|           children: [
 | |
|             IconButton(
 | |
|               icon: const Icon(Icons.remove_circle_outline, size: 20),
 | |
|               splashRadius: 18,
 | |
|               onPressed: value > min
 | |
|                   ? () {
 | |
|                       value--;
 | |
|                       controller.text = value.toString();
 | |
|                       (context as Element).markNeedsBuild();
 | |
|                     }
 | |
|                   : null,
 | |
|             ),
 | |
|             SizedBox(
 | |
|               width: 60,
 | |
|               height: 36,
 | |
|               child: TextFormField(
 | |
|                 controller: controller,
 | |
|                 keyboardType: TextInputType.number,
 | |
|                 textAlign: TextAlign.center,
 | |
|                 style: const TextStyle(fontSize: 15),
 | |
|                 decoration: const InputDecoration(
 | |
|                   border: OutlineInputBorder(),
 | |
|                   contentPadding:
 | |
|                       EdgeInsets.symmetric(vertical: 6, horizontal: 6),
 | |
|                 ),
 | |
|                 onChanged: (val) {
 | |
|                   int? v = int.tryParse(val);
 | |
|                   if (v == null || v < min) {
 | |
|                     controller.text = min.toString();
 | |
|                   } else if (v > max) {
 | |
|                     controller.text = max.toString();
 | |
|                   }
 | |
|                 },
 | |
|               ),
 | |
|             ),
 | |
|             IconButton(
 | |
|               icon: const Icon(Icons.add_circle_outline, size: 20),
 | |
|               splashRadius: 18,
 | |
|               onPressed: value < max
 | |
|                   ? () {
 | |
|                       value++;
 | |
|                       controller.text = value.toString();
 | |
|                       (context as Element).markNeedsBuild();
 | |
|                     }
 | |
|                   : null,
 | |
|             ),
 | |
|           ],
 | |
|         ),
 | |
|       ],
 | |
|     );
 | |
|   }
 | |
| }
 |