LCOV - code coverage report
Current view: top level - widgets/buttons - slider_button.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 86 88 97.7 %
Date: 2022-07-13 09:29:13 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:basf_flutter_components/basf_flutter_components.dart';
       2             : import 'package:flutter/material.dart';
       3             : 
       4             : /// {@template basf_slider_button}
       5             : /// A BASF-styled slider button
       6             : /// {@endtemplate}
       7             : class SliderButton extends StatefulWidget {
       8             :   /// {@macro basf_slider_button}
       9           1 :   const SliderButton({
      10             :     super.key,
      11             :     this.height = 70,
      12             :     this.width = 300,
      13             :     this.backgroundColor = Colors.white,
      14             :     this.backgroundColorEnd,
      15             :     this.foregroundColor,
      16             :     this.iconColor = Colors.white,
      17             :     this.shadow,
      18             :     this.sliderButtonContent,
      19             :     this.text,
      20             :     this.textStyle,
      21             :     required this.onConfirmation,
      22             :     this.foregroundShape,
      23             :     this.backgroundShape,
      24             :     this.stickToEnd = false,
      25             :     this.animationCurve,
      26             :   }) : assert(
      27           3 :           height >= 25 && width >= 250,
      28             :           '''Height must be be greater or equal to 25, and width greater or equal to 250''',
      29             :         );
      30             : 
      31             :   /// Height of the slider
      32             :   final double height;
      33             : 
      34             :   /// Width of the slider
      35             :   final double width;
      36             : 
      37             :   /// Background color of the slider
      38             :   final Color backgroundColor;
      39             : 
      40             :   /// Background color of the slider on the end
      41             :   final Color? backgroundColorEnd;
      42             : 
      43             :   /// Background color of the slider on the foreground
      44             :   final Color? foregroundColor;
      45             : 
      46             :   /// Icon color of the icon in the slider
      47             :   final Color iconColor;
      48             : 
      49             :   /// An optional slider cuntent as a widget
      50             :   final Widget? sliderButtonContent;
      51             : 
      52             :   /// Slider shadows
      53             :   final BoxShadow? shadow;
      54             : 
      55             :   /// Slider text
      56             :   final String? text;
      57             : 
      58             :   /// Slider text style
      59             :   final TextStyle? textStyle;
      60             : 
      61             :   /// Action to be performed when the slider is fully slided
      62             :   final VoidCallback onConfirmation;
      63             : 
      64             :   /// Shape of the slider
      65             :   final BorderRadius? foregroundShape;
      66             : 
      67             :   /// Shape of the slider's background
      68             :   final BorderRadius? backgroundShape;
      69             : 
      70             :   /// Wheter or not the slider should stick to the end of the shape on drag
      71             :   final bool stickToEnd;
      72             : 
      73             :   /// Curve of the slider animation
      74             :   final Curve? animationCurve;
      75             : 
      76           1 :   @override
      77             :   State<StatefulWidget> createState() {
      78           1 :     return _SliderButtonState();
      79             :   }
      80             : }
      81             : 
      82             : class _SliderButtonState extends State<SliderButton> {
      83             :   double _position = 0;
      84             :   int _duration = 0;
      85             : 
      86           1 :   @override
      87             :   Widget build(BuildContext context) {
      88           1 :     return AnimatedContainer(
      89           2 :       duration: Duration(milliseconds: _duration),
      90             :       curve: Curves.ease,
      91           2 :       height: widget.height,
      92           2 :       width: widget.width,
      93             :       padding: const EdgeInsets.all(5),
      94           1 :       decoration: BoxDecoration(
      95           3 :         borderRadius: widget.backgroundShape ?? BasfThemes.defaultBorderRadius,
      96           2 :         color: widget.backgroundColorEnd != null
      97           1 :             ? _calculateBackground()
      98           2 :             : widget.backgroundColor,
      99           1 :         boxShadow: [
     100           2 :           widget.shadow ??
     101             :               const BoxShadow(
     102             :                 color: Colors.black38,
     103             :                 offset: Offset(0, 1),
     104             :                 blurRadius: 2,
     105             :               ),
     106             :         ],
     107             :       ),
     108           1 :       child: Stack(
     109           1 :         children: [
     110           1 :           _text(),
     111           1 :           _backgroundOverlay(),
     112           1 :           _sliderButton(),
     113             :         ],
     114             :       ),
     115             :     );
     116             :   }
     117             : 
     118           1 :   Widget _text() {
     119           1 :     return Center(
     120           1 :       child: Text(
     121           2 :         widget.text ?? '',
     122           2 :         style: widget.textStyle ??
     123             :             const TextStyle(
     124             :               color: Colors.black26,
     125             :               fontWeight: FontWeight.bold,
     126             :             ),
     127             :         maxLines: 2,
     128             :         overflow: TextOverflow.ellipsis,
     129             :       ),
     130             :     );
     131             :   }
     132             : 
     133           1 :   Widget _backgroundOverlay() {
     134           1 :     return Positioned(
     135           3 :       left: widget.height / 2,
     136           1 :       child: AnimatedContainer(
     137           3 :         height: widget.height - 10,
     138           1 :         width: _getPosition(),
     139           2 :         duration: Duration(milliseconds: _duration),
     140             :         curve: Curves.ease,
     141           1 :         decoration: BoxDecoration(
     142           2 :           borderRadius: widget.backgroundShape ??
     143           4 :               BorderRadius.all(Radius.circular(widget.height)),
     144           2 :           color: widget.backgroundColorEnd != null
     145           1 :               ? _calculateBackground()
     146           2 :               : widget.backgroundColor,
     147             :         ),
     148             :       ),
     149             :     );
     150             :   }
     151             : 
     152           1 :   Widget _sliderButton() {
     153           1 :     return AnimatedPositioned(
     154           2 :       duration: Duration(milliseconds: _duration),
     155           2 :       curve: widget.animationCurve ?? Curves.easeOutCubic,
     156           1 :       left: _getPosition(),
     157             :       top: 0,
     158           1 :       child: GestureDetector(
     159           1 :         onPanUpdate: _updatePosition,
     160           1 :         onPanEnd: _sliderReleased,
     161           1 :         child: Container(
     162           3 :           height: widget.height - 10,
     163           3 :           width: widget.height - 10,
     164           1 :           decoration: BoxDecoration(
     165             :             borderRadius:
     166           3 :                 widget.foregroundShape ?? BasfThemes.defaultBorderRadius,
     167           5 :             color: widget.foregroundColor ?? Theme.of(context).primaryColor,
     168             :           ),
     169           2 :           child: widget.sliderButtonContent ??
     170           1 :               Icon(
     171             :                 Icons.navigate_next,
     172           2 :                 color: widget.iconColor,
     173             :               ),
     174             :         ),
     175             :       ),
     176             :     );
     177             :   }
     178             : 
     179           1 :   double _getPosition() {
     180           2 :     if (_position < 0) {
     181             :       return 0;
     182           7 :     } else if (_position > widget.width - widget.height) {
     183           0 :       return widget.width - widget.height;
     184             :     } else {
     185           1 :       return _position;
     186             :     }
     187             :   }
     188             : 
     189           1 :   void _updatePosition(dynamic details) {
     190           1 :     if (details is DragEndDetails) {
     191           2 :       setState(() {
     192           1 :         _duration = 600;
     193           9 :         if (widget.stickToEnd && _position > widget.width - widget.height) {
     194           6 :           _position = widget.width - widget.height;
     195             :         } else {
     196           1 :           _position = 0;
     197             :         }
     198             :       });
     199           1 :     } else if (details is DragUpdateDetails) {
     200           2 :       setState(() {
     201           1 :         _duration = 0;
     202           7 :         _position = details.localPosition.dx - (widget.height / 2);
     203             :       });
     204             :     }
     205             :   }
     206             : 
     207           1 :   void _sliderReleased(DragEndDetails details) {
     208           7 :     if (_position > widget.width - widget.height) {
     209           3 :       widget.onConfirmation();
     210             :     }
     211           1 :     _updatePosition(details);
     212             :   }
     213             : 
     214           1 :   Color _calculateBackground() {
     215           2 :     if (widget.backgroundColorEnd != null) {
     216             :       double percent;
     217             : 
     218             :       // calculates the percentage of the position of the slider
     219           7 :       if (_position > widget.width - widget.height) {
     220             :         percent = 1.0;
     221           8 :       } else if (_position / (widget.width - widget.height) > 0) {
     222           7 :         percent = _position / (widget.width - widget.height);
     223             :       } else {
     224             :         percent = 0.0;
     225             :       }
     226             : 
     227           3 :       final red = widget.backgroundColorEnd!.red;
     228           3 :       final green = widget.backgroundColorEnd!.green;
     229           3 :       final blue = widget.backgroundColorEnd!.blue;
     230             : 
     231           1 :       return Color.alphaBlend(
     232           1 :         Color.fromRGBO(red, green, blue, percent),
     233           2 :         widget.backgroundColor,
     234             :       );
     235             :     } else {
     236           0 :       return widget.backgroundColor;
     237             :     }
     238             :   }
     239             : }

Generated by: LCOV version 1.16