You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PatientApp-KKUMC/lib/widgets/CounterView.dart

189 lines
5.6 KiB
Dart

import 'package:flutter/material.dart';
typedef StepperCallbackFuture = Future<bool> Function(int apply, int total);
class StepperView extends StatefulWidget {
final double height;
final Color foregroundColor;
final Color backgroundColor;
final double buttonPadding;
final int initialNumber;
final int maxNumber;
final int minNumber;
final StepperCallbackFuture? counterCallback;
final Function? increaseCallback;
final Function? decreaseCallback;
StepperView({this.initialNumber = 1, this.minNumber = 1, required this.maxNumber, @required this.counterCallback, this.increaseCallback, this.decreaseCallback, this.height = 25, required this.foregroundColor, required this.backgroundColor, this.buttonPadding = 1}){
assert((this.initialNumber >= this.minNumber && this.initialNumber <= this.maxNumber));
}
@override
_StepperViewState createState() => _StepperViewState();
}
class _StepperViewState extends State<StepperView> {
late int _currentCount;
late StepperCallbackFuture _counterCallback;
late Function _increaseCallback;
late Function _decreaseCallback;
@override
void initState() {
_currentCount = widget.initialNumber ?? 1;
_counterCallback = widget.counterCallback!;
_increaseCallback = widget.increaseCallback ?? () {};
_decreaseCallback = widget.decreaseCallback ?? () {};
super.initState();
}
bool loadingInc = false;
bool loadingDec = false;
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(widget.buttonPadding),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular((widget.height/2) + (widget.buttonPadding*2)),
color: widget.backgroundColor,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_createDecrementButton(
((_currentCount > widget.minNumber) ? () => _decrement() : null) as VoidCallback,
),
Container(
width: 25,
child: Center(
child: Text(
_currentCount.toString(),
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
height: 1.5,
color: Colors.black,
)
),
)
),
_createIncrementButton(
((_currentCount < widget.maxNumber) ? () => _increment() : null) as VoidCallback
),
],
),
);
}
void _increment() async{
doInc({required bool can}){
if(can)
setState(() {
_currentCount++;
_increaseCallback();
});
}
if (_currentCount < widget.maxNumber){
if(_counterCallback == null)
doInc(can: true);
else {
setState(() => loadingInc = true);
var result = (await _counterCallback(1,_currentCount));
doInc(can: result);
setState(() => loadingInc = false);
}
}
}
void _decrement() async{
doDec({required bool can}){
if(can)
setState(() {
_currentCount--;
_decreaseCallback();
});
}
if (_currentCount > widget.minNumber) {
if(_counterCallback == null)
doDec(can: true);
else {
setState(() => loadingDec = true);
var result = (await _counterCallback(-1,_currentCount));
doDec(can: result);
setState(() => loadingDec = false);
}
}
}
Widget _createIncrementButton(VoidCallback onPressed,) {
return Stack(
children: [
RawMaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
constraints: BoxConstraints(minWidth: widget.height, minHeight: widget.height),
onPressed: onPressed,
elevation: 2.0,
fillColor: widget.foregroundColor,
child:
Icon(
Icons.add,
color: (_currentCount < widget.maxNumber) ? Colors.grey[700] : Colors.grey[400],
size: 12.0,
),
shape: CircleBorder(),
),
if(loadingInc)
Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.8),
borderRadius: BorderRadius.circular(widget.height/2),
),
height: widget.height,
width: widget.height,
child: CircularProgressIndicator(
strokeWidth: 3,
valueColor: AlwaysStoppedAnimation<Color>(Colors.green)
)
)
],
);
}
Widget _createDecrementButton(VoidCallback onPressed) {
return Stack(
children: [
RawMaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
constraints: BoxConstraints(minWidth: widget.height, minHeight: widget.height),
onPressed: onPressed,
elevation: 2.0,
fillColor: widget.foregroundColor,
child: Icon(
Icons.remove,
color: (_currentCount > widget.minNumber) ? Colors.grey[700] : Colors.grey[400],
size: 12.0,
),
shape: CircleBorder(),
),
if(loadingDec)
Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.8),
borderRadius: BorderRadius.circular(widget.height/2),
),
height: widget.height,
width: widget.height,
child: CircularProgressIndicator(
strokeWidth: 3,
valueColor: AlwaysStoppedAnimation<Color>(Colors.red)
)
)
],
);
}
}