diff --git a/example/lib/main.dart b/example/lib/main.dart index e80fd5c3..d58cdf9d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -30,12 +30,16 @@ import 'package:flutter/cupertino.dart'; import 'package:ui_kit/size/gf_size.dart'; import 'package:ui_kit/position/gf_position.dart'; import 'package:ui_kit/components/tabs/gf_tabs.dart'; +import 'package:ui_kit/components/slider/gf_items_slider.dart'; +import 'package:ui_kit/components/drawer/gf_drawer.dart'; final List imageList = [ "https://cdn.pixabay.com/photo/2017/12/03/18/04/christmas-balls-2995437_960_720.jpg", "https://cdn.pixabay.com/photo/2017/12/13/00/23/christmas-3015776_960_720.jpg", "https://cdn.pixabay.com/photo/2019/12/19/10/55/christmas-market-4705877_960_720.jpg", - "https://cdn.pixabay.com/photo/2019/12/20/00/03/road-4707345_960_720.jpg" + "https://cdn.pixabay.com/photo/2019/12/20/00/03/road-4707345_960_720.jpg", + "https://cdn.pixabay.com/photo/2019/12/22/04/18/x-mas-4711785__340.jpg", + "https://cdn.pixabay.com/photo/2016/11/22/07/09/spruce-1848543__340.jpg" ]; void main() => runApp(MyApp()); @@ -68,9 +72,53 @@ class _MyHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( + drawer: GFDrawer( + colorFilter: new ColorFilter.mode(Colors.black.withOpacity(0.6), BlendMode.darken), + backgroundImage: NetworkImage("https://cdn.pixabay.com/photo/2017/12/03/18/04/christmas-balls-2995437_960_720.jpg"), + gradient: LinearGradient( + begin: Alignment.topRight, + end: Alignment.bottomLeft, + stops: [0.1, 0.5, 0.7, 0.9], + colors: [ + Colors.teal[800], + Colors.teal[600], + Colors.teal[400], + Colors.teal[200], + ], + ), + child: ListView( + padding: EdgeInsets.zero, + children: [ + UserAccountsDrawerHeader(), + DrawerHeader( + child: Column( + children: [ + Text('Drawer Header'), + Text('Drawer Header'), + Text('Drawer Header'), + ], + ), + decoration: BoxDecoration( + color: Colors.blue, + ), + ), + ListTile( + title: Text('Item 1'), + onTap: () { + }, + ), + ListTile( + title: Text('Item 2'), + onTap: () { + }, + ), + ], + ), + ), backgroundColor: Colors.cyanAccent, appBar: AppBar( title: Text(widget.title), + ), body: SingleChildScrollView( child: Column( @@ -78,13 +126,33 @@ class _MyHomePageState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ + GFItemsSlider( + rowCount: 3, + children: imageList.map( + (url) { + return Container( + margin: EdgeInsets.all(5.0), + child: ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(5.0)), + child: Image.network( + url, + fit: BoxFit.cover, + width: 1000.0 + ), + ), + ); + }, + ).toList(), + ), + GFSlider( -// pagerSize: 12.0, -// activeIndicator: Colors.pink, -// passiveIndicator: Colors.pink.withOpacity(0.4), - viewportFraction: 0.9, + rowCount: 3, + pagerSize: 12.0, + activeIndicator: Colors.pink, + passiveIndicator: Colors.pink.withOpacity(0.4), + viewportFraction: 1.0, aspectRatio: 2.0, -// autoPlay: true, + autoPlay: true, enlargeMainPage: true, pagination: true, items: imageList.map( @@ -96,7 +164,7 @@ class _MyHomePageState extends State { child: Image.network( url, fit: BoxFit.cover, - width: 1000.0, + width: 1000.0 ), ), ); @@ -109,20 +177,20 @@ class _MyHomePageState extends State { }, ), - GFButton( - color: Colors.orange, - onPressed: null, - child: Text("share"), - type: GFType.outline, - shape: GFShape.pills, -// buttonBoxShadow: true, -// boxShadow: BoxShadow( -// color: Colors.pink, -// blurRadius: 1.5, -// spreadRadius: 2.0, -// offset: Offset.zero, -// ), - ), +// GFButton( +// color: Colors.orange, +// onPressed: null, +// child: Text("share"), +// type: GFType.outline, +// shape: GFShape.pills, +//// buttonBoxShadow: true, +//// boxShadow: BoxShadow( +//// color: Colors.pink, +//// blurRadius: 1.5, +//// spreadRadius: 2.0, +//// offset: Offset.zero, +//// ), +// ), GFTabs( initialIndex: 0, @@ -174,22 +242,22 @@ class _MyHomePageState extends State { Icon(Icons.directions_transit), ], ), -// indicatorColor: Colors.teal, -// indicatorSize: TabBarIndicatorSize.label, -// labelColor: Colors.lightGreen, -// unselectedLabelColor: Colors.black, -// labelStyle: TextStyle( -// fontWeight: FontWeight.w500, -// fontSize: 13.0, -// color: Colors.deepOrange, -// fontFamily: 'OpenSansBold', -// ), -// unselectedLabelStyle: TextStyle( -// fontWeight: FontWeight.w500, -// fontSize: 13.0, -// color: Colors.black, -// fontFamily: 'OpenSansBold', -// ), + indicatorColor: Colors.teal, + indicatorSize: TabBarIndicatorSize.label, + labelColor: Colors.lightGreen, + unselectedLabelColor: Colors.black, + labelStyle: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 13.0, + color: Colors.deepOrange, + fontFamily: 'OpenSansBold', + ), + unselectedLabelStyle: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 13.0, + color: Colors.black, + fontFamily: 'OpenSansBold', + ), ), // GFSlider( @@ -217,77 +285,80 @@ class _MyHomePageState extends State { // }); // }, // ), - GFCard( - boxFit: BoxFit.cover, - colorFilter: new ColorFilter.mode( - Colors.black.withOpacity(0.67), BlendMode.darken), - image: Image.asset("lib/assets/food.jpeg"), -// imageOverlay: AssetImage("lib/assets/food.jpeg"), - titlePosition: GFPosition.end, - title: GFListTile( - avatar: GFAvatar( - child: Text("tb"), - ), - title: Text( - 'title', - style: TextStyle(color: Colors.grey), - ), - subTitle: Text( - 'subtitle', - style: TextStyle(color: Colors.grey), - ), - icon: GFIconButton( - onPressed: null, - icon: Icon(Icons.favorite_border), - type: GFType.transparent, - ), - ), - content: Text( - "Flutter " - "Flutter is Google's mobile UI framework for crafting" - " high-quality native interfaces on iOS and Android in " - "Flutter ", - style: TextStyle(color: Colors.grey), - ), - buttonBar: GFButtonBar( - mainAxisSize: MainAxisSize.min, - children: [ - GFButton( - onPressed: null, - child: Text("favorite"), - icon: Icon(Icons.favorite_border), - type: GFType.transparent, - ), - GFButton( - onPressed: null, - child: Text("share"), - icon: Icon(Icons.share), - type: GFType.outline, - ), - ], - ), - ), - GFButtonBar( - mainAxisSize: MainAxisSize.min, - children: [ - GFButton( - onPressed: null, - child: Text("like"), - icon: Icon(Icons.favorite_border), - type: GFType.transparent, - ), - GFButton( - onPressed: null, - child: Text("comment"), - ), +// GFCard( +// boxFit: BoxFit.cover, +// colorFilter: new ColorFilter.mode( +// Colors.black.withOpacity(0.67), BlendMode.darken), +// image: Image.asset("lib/assets/food.jpeg"), +//// imageOverlay: AssetImage("lib/assets/food.jpeg"), +// titlePosition: GFPosition.end, +// title: GFListTile( +// avatar: GFAvatar( +// child: Text("tb"), +// ), +// title: Text( +// 'title', +// style: TextStyle(color: Colors.grey), +// ), +// subTitle: Text( +// 'subtitle', +// style: TextStyle(color: Colors.grey), +// ), +// icon: GFIconButton( +// onPressed: null, +// icon: Icon(Icons.favorite_border), +// type: GFType.transparent, +// ), +// ), +// content: Text( +// "Flutter " +// "Flutter is Google's mobile UI framework for crafting" +// " high-quality native interfaces on iOS and Android in " +// "Flutter ", +// style: TextStyle(color: Colors.grey), +// ), +// buttonBar: GFButtonBar( +// mainAxisSize: MainAxisSize.min, +// children: [ +// GFButton( +// onPressed: null, +// child: Text("favorite"), +// icon: Icon(Icons.favorite_border), +// type: GFType.transparent, +// ), +// GFButton( +// onPressed: null, +// child: Text("share"), +// icon: Icon(Icons.share), +// type: GFType.outline, +// ), +// ], +// ), +// ), +// GFButtonBar( +// mainAxisSize: MainAxisSize.min, +// children: [ +// GFButton( +// onPressed: null, +// child: Text("like"), +// icon: Icon(Icons.favorite_border), +// type: GFType.transparent, +// ), +// GFButton( +// onPressed: null, +// child: Text("comment"), +// ), GFButton( - onPressed: null, + color: Colors.teal, + onPressed: (){}, child: Text("share"), icon: Icon(Icons.share), type: GFType.outline, ), - ], - ), +// ], +// ), + + // GFListItem( // avatar: GFAvatar( // child: Text("tb"), diff --git a/lib/components/button/gf_button.dart b/lib/components/button/gf_button.dart index 58a86555..56639e69 100644 --- a/lib/components/button/gf_button.dart +++ b/lib/components/button/gf_button.dart @@ -302,32 +302,11 @@ class _GFButtonState extends State { } - double get _effectiveElevation { - // These conditionals are in order of precedence, so be careful about - // reorganizing them. - if (_disabled) { - return widget.disabledElevation; - } - if (_pressed) { - return widget.highlightElevation; - } - if (_hovered) { - return widget.hoverElevation; - } - if (_focused) { - return widget.focusElevation; - } - return widget.elevation; - } - - @override Widget build(BuildContext context) { ShapeBorder shape; - final ShapeBorder effectiveShape = MaterialStateProperty.resolveAs(shape, _states); - final Color effectiveTextColor = MaterialStateProperty.resolveAs( widget.textStyle?.color, _states); final Color themeColor = @@ -410,7 +389,6 @@ class _GFButtonState extends State { BoxConstraints(minHeight: 26.0, minWidth: 98.0), decoration: getBoxShadow(), child: Material( - elevation: _effectiveElevation, textStyle: widget.textStyle == null ? TextStyle(color: this.textColor, fontSize: 14) : widget.textStyle, shape: widget.type == GFType.transparent ? null : widget.borderShape == null ? shape : widget.borderShape, color: widget.type == GFType.transparent || widget.type == GFType.outline ? Colors.transparent : this.color, diff --git a/lib/components/drawer/gf_drawer.dart b/lib/components/drawer/gf_drawer.dart new file mode 100644 index 00000000..fb0695de --- /dev/null +++ b/lib/components/drawer/gf_drawer.dart @@ -0,0 +1,212 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter/material.dart'; + +/// The possible alignments of a [GFDrawer]. +enum GFDrawerAlignment { + /// Denotes that the [GFDrawer] is at the start side of the [Scaffold]. + /// + /// This corresponds to the left side when the text direction is left-to-right + /// and the right side when the text direction is right-to-left. + start, + + /// Denotes that the [GFDrawer] is at the end side of the [Scaffold]. + /// + /// This corresponds to the right side when the text direction is left-to-right + /// and the left side when the text direction is right-to-left. + end, +} + +// TODO(eseidel): Draw width should vary based on device size: +// https://material.io/design/components/navigation-drawer.html#specs + +// Mobile: +// Width = Screen width − 56 dp +// Maximum width: 320dp +// Maximum width applies only when using a left nav. When using a right nav, +// the panel can cover the full width of the screen. + +// Desktop/Tablet: +// Maximum width for a left nav is 400dp. +// The right nav can vary depending on content. + +const double _kWidth = 304.0; +const double _kEdgeDragWidth = 20.0; +const double _kMinFlingVelocity = 365.0; +const Duration _kBaseSettleDuration = Duration(milliseconds: 246); + +/// A material design panel that slides in horizontally from the edge of a +/// [Scaffold] to show navigation links in an application. +/// +/// GFDrawers are typically used with the [Scaffold.drawer] property. The child of +/// the drawer is usually a [ListView] whose first child is a [GFDrawerHeader] +/// that displays status information about the current user. The remaining +/// drawer children are often constructed with [ListTile]s, often concluding +/// with an [AboutListTile]. +/// +/// The [AppBar] automatically displays an appropriate [IconButton] to show the +/// [GFDrawer] when a [GFDrawer] is available in the [Scaffold]. The [Scaffold] +/// automatically handles the edge-swipe gesture to show the drawer. +/// +/// {@animation 350 622 https://flutter.github.io/assets-for-api-docs/assets/material/drawer.mp4} +/// +/// {@tool sample} +/// This example shows how to create a [Scaffold] that contains an [AppBar] and +/// a [GFDrawer]. A user taps the "menu" icon in the [AppBar] to open the +/// [GFDrawer]. The [GFDrawer] displays four items: A header and three menu items. +/// The [GFDrawer] displays the four items using a [ListView], which allows the +/// user to scroll through the items if need be. +/// +/// ```dart +/// Scaffold( +/// appBar: AppBar( +/// title: const Text('GFDrawer Demo'), +/// ), +/// drawer: GFDrawer( +/// child: ListView( +/// padding: EdgeInsets.zero, +/// children: const [ +/// GFDrawerHeader( +/// decoration: BoxDecoration( +/// color: Colors.blue, +/// ), +/// child: Text( +/// 'GFDrawer Header', +/// style: TextStyle( +/// color: Colors.white, +/// fontSize: 24, +/// ), +/// ), +/// ), +/// ListTile( +/// leading: Icon(Icons.message), +/// title: Text('Messages'), +/// ), +/// ListTile( +/// leading: Icon(Icons.account_circle), +/// title: Text('Profile'), +/// ), +/// ListTile( +/// leading: Icon(Icons.settings), +/// title: Text('Settings'), +/// ), +/// ], +/// ), +/// ), +/// ) +/// ``` +/// {@end-tool} +/// +/// An open drawer can be closed by calling [Navigator.pop]. For example +/// a drawer item might close the drawer when tapped: +/// +/// ```dart +/// ListTile( +/// leading: Icon(Icons.change_history), +/// title: Text('Change history'), +/// onTap: () { +/// // change app state... +/// Navigator.pop(context); // close the drawer +/// }, +/// ); +/// ``` +/// +/// See also: +/// +/// * [Scaffold.drawer], where one specifies a [GFDrawer] so that it can be +/// shown. +/// * [Scaffold.of], to obtain the current [ScaffoldState], which manages the +/// display and animation of the drawer. +/// * [ScaffoldState.openGFDrawer], which displays its [GFDrawer]. +/// +class GFDrawer extends StatelessWidget { + /// Creates a material design drawer. + /// + /// Typically used in the [Scaffold.drawer] property. + /// + /// The [elevation] must be non-negative. + const GFDrawer({ + Key key, + this.elevation = 16.0, + this.child, + this.semanticLabel, + this.backgroundImage, + this.colorFilter, + this.gradient + }) : assert(elevation != null && elevation >= 0.0), + super(key: key); + + /// The z-coordinate at which to place this drawer relative to its parent. + /// + /// This controls the size of the shadow below the drawer. + /// + /// Defaults to 16, the appropriate elevation for drawers. The value is + /// always non-negative. + final double elevation; + + /// The widget below this widget in the tree. + /// + /// Typically a [SliverList]. + /// + /// {@macro flutter.widgets.child} + final Widget child; + + /// The semantic label of the dialog used by accessibility frameworks to + /// announce screen transitions when the drawer is opened and closed. + /// + /// If this label is not provided, it will default to + /// [MaterialLocalizations.drawerLabel]. + /// + /// See also: + /// + /// * [SemanticsConfiguration.namesRoute], for a description of how this + /// value is used. + final String semanticLabel; + + /// Background image can be added to the [GFDrawer]. + final ImageProvider backgroundImage; + + /// A composited layer that applies a color filter to its children. + final ColorFilter colorFilter; + + /// + final Gradient gradient; + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); + String label = semanticLabel; + switch (Theme.of(context).platform) { + case TargetPlatform.iOS: + label = semanticLabel; + break; + case TargetPlatform.android: + case TargetPlatform.fuchsia: + label = semanticLabel ?? MaterialLocalizations.of(context)?.drawerLabel; + } + return Semantics( + scopesRoute: true, + namesRoute: true, + explicitChildNodes: true, + label: label, + child: ConstrainedBox( + constraints: const BoxConstraints.expand(width: _kWidth), + child: Material( + elevation: elevation, + child: Container( + decoration: new BoxDecoration( + color: Colors.teal, + gradient: gradient, + image: backgroundImage != null ? new DecorationImage( + image: backgroundImage, + fit: BoxFit.cover, + colorFilter: colorFilter, + ) : null, + ), + child: child + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/components/slider/gf_items_slider.dart b/lib/components/slider/gf_items_slider.dart new file mode 100644 index 00000000..3702ef7b --- /dev/null +++ b/lib/components/slider/gf_items_slider.dart @@ -0,0 +1,218 @@ +library carousel; + +import 'dart:async'; + +import 'package:flutter/material.dart'; + +/// Signature for when a pointer has contacted the screen and has begun to move. +/// +/// The `details` object provides the position of the touch when it first +/// touched the surface. +typedef GFItemsSliderSlideStartCallback = void Function(DragStartDetails details); + +/// Signature for when a pointer that is in contact with the screen and moving +/// has moved again. +/// +/// The `details` object provides the position of the touch and the distance it +/// has travelled since the last update. +typedef GFItemsSliderSlideCallback = void Function(DragUpdateDetails details); + +/// Signature for when a pointer that was previously in contact with the screen +/// and moving is no longer in contact with the screen. +/// +/// The velocity at which the pointer was moving when it stopped contacting +/// the screen is available in the `details`. +typedef GFItemsSliderSlideEndCallback = void Function(DragEndDetails details); + +/// A widget that show draggable cells with animation. +/// +/// Set [rowCount] of visible cells +/// +/// Set drag handlers [onSlideStart], [onSlide], [onSlideEnd] +/// +/// Set left/right arrows [leftArrow], [rightArrow] +class GFItemsSlider extends StatefulWidget { + /// Count of visible cells + int rowCount; + + List children; + + /// Signature for when a pointer has contacted the screen and has begun to move. + GFItemsSliderSlideStartCallback onSlideStart; + + /// Signature for when a pointer that is in contact with the screen and moving + /// has moved again. + GFItemsSliderSlideCallback onSlide; + + /// Signature for when a pointer that was previously in contact with the screen + /// and moving is no longer in contact with the screen. + GFItemsSliderSlideEndCallback onSlideEnd; + + GFItemsSlider({ + this.rowCount, + this.children, + this.onSlideStart, + this.onSlide, + this.onSlideEnd + }); + + @override + _GFItemsSliderState createState() => new _GFItemsSliderState(); +} + +class _GFItemsSliderState extends State with TickerProviderStateMixin { + /// In milliseconds + static final int DRAG_ANIMATION_DURATION = 1000; + + /// In milliseconds + static final int SHIFT_ANIMATION_DURATION = 300; + + /// Size of cell + double size = 0; + + /// Width of cells container + double width = 0; + + AnimationController animationController; + + /// Shift of cells container + double offset; + + @override + void initState() { + super.initState(); + + this.offset = 0; + + this.animationController = AnimationController( + duration: new Duration(milliseconds: DRAG_ANIMATION_DURATION), + vsync: this + ); + + new Future.delayed(Duration.zero, () { + this.setState(() { + + double width = MediaQuery.of(context).size.width; + this.width = width; + this.size = this.width / widget.rowCount; + }); + }); + } + + double calculateOffset(double shift) { + double offset = this.offset + shift; + double rightLimit = this.size * (widget.children.length - widget.rowCount); + + /// Check cells container limits + if (offset > 0) { + offset = 0; + } else if (offset < -rightLimit) { + offset = -rightLimit; + } + + return offset; + } + + onSlideStart(DragStartDetails details) { + this.animationController.stop(); + widget.onSlideStart != null ? widget.onSlideStart(details) : null; + } + + onSlide(DragUpdateDetails details) { + setState(() { + this.offset = this.calculateOffset(3 * details.delta.dx); + }); + + widget.onSlide != null ? widget.onSlide(details) : null; + } + + onSlideEnd(DragEndDetails details) { + double dx = details.velocity.pixelsPerSecond.dx; + + if (dx == 0) { + return this.runShiftAnimation(); + } + + this.animationController = new AnimationController( + duration: new Duration(milliseconds: DRAG_ANIMATION_DURATION), + vsync: this + ); + + Tween tween = new Tween( + begin: this.offset, + end: this.calculateOffset(0.5 * dx) + ); + + Animation animation = tween.animate( + new CurvedAnimation( + parent: this.animationController, + curve: Curves.easeOut, + ) + ); + + animation.addStatusListener((AnimationStatus status) { + if (status == AnimationStatus.completed) { + this.runShiftAnimation(); + } + }); + + animation.addListener(() { + setState(() { + this.offset = animation.value; + }); + }); + + this.animationController.forward(); + widget.onSlideEnd != null ? widget.onSlideEnd(details) : null; + } + + runShiftAnimation() { + double beginAnimation = this.offset; + double endAnimation = + this.size * (this.offset / this.size).round().toDouble(); + + this.animationController = new AnimationController( + duration: new Duration(milliseconds: SHIFT_ANIMATION_DURATION), + vsync: this + ); + Tween tween = new Tween(begin: beginAnimation, end: endAnimation); + Animation animation = tween.animate(this.animationController); + + animation.addListener(() { + setState(() { + this.offset = animation.value; + }); + }); + + this.animationController.forward(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onHorizontalDragStart: this.onSlideStart, + onHorizontalDragUpdate: this.onSlide, + onHorizontalDragEnd: this.onSlideEnd, + child: Container( + width: double.infinity, + height: this.size, + child: Stack( + children: [ + Positioned( + left: this.offset, + child: Row( + children: widget.children.map((child) { + return Container( + width: this.size, + height: this.size, + child: child, + ); + }).toList(), + ), + ), + ] + ), + ), + ); + } +} diff --git a/lib/components/slider/gf_slider.dart b/lib/components/slider/gf_slider.dart index fe3a4846..2dc91648 100644 --- a/lib/components/slider/gf_slider.dart +++ b/lib/components/slider/gf_slider.dart @@ -32,6 +32,7 @@ class GFSlider extends StatefulWidget { this.enlargeMainPage = false, this.onPageChanged, this.scrollPhysics, + this.rowCount, this.scrollDirection: Axis.horizontal}) : this.realPage = enableInfiniteScroll ? realPage + initialPage : initialPage, @@ -41,6 +42,9 @@ class GFSlider extends StatefulWidget { enableInfiniteScroll ? realPage + initialPage : initialPage, ); + /// Count of visible cells + int rowCount; + /// The pagination dots size can be defined using [double]. final double pagerSize; @@ -164,10 +168,26 @@ class GFSlider extends StatefulWidget { class _GFSliderState extends State with TickerProviderStateMixin { Timer timer; + /// Size of cell + double size = 0; + + /// Width of cells container + double width = 0; + @override void initState() { super.initState(); timer = getPlayTimer(); + + new Future.delayed(Duration.zero, () { + this.setState(() { + + double width = MediaQuery.of(context).size.width; + this.width = width; + this.size = this.width / widget.rowCount; + }); + }); + } Timer getPlayTimer() { @@ -213,10 +233,13 @@ class _GFSliderState extends State with TickerProviderStateMixin { int _current = 0; + @override Widget build(BuildContext context) { + return Stack( children: [ + getPageWrapper(PageView.builder( physics: widget.scrollPhysics, scrollDirection: widget.scrollDirection, @@ -262,13 +285,16 @@ class _GFSliderState extends State with TickerProviderStateMixin { if (widget.scrollDirection == Axis.horizontal) { return Center( child: SizedBox( - height: distortionValue * height, child: child)); + height: distortionValue * height, child: child), + + ); } else { return Center( child: SizedBox( width: distortionValue * MediaQuery.of(context).size.width, - child: child)); + child: child), + ); } }, );