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.
		
		
		
		
		
			
		
			
				
	
	
		
			189 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			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)
 | 
						|
              )
 | 
						|
          )
 | 
						|
      ],
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |