Sliding Sheet Flutter Example

In this article, we are going to learn how to create sliding sheet in flutter applications. You can also check out Bottom Sheet related article at HERE.

In this example, we are creating bottom sheet to display football player names. Then we can slide these sheet from bottom to top. In this bottom sheet, we can stick header and footer view and only scroll body part.

To create this type of sheet, we are using flutter package sliding_sheet. Sliding sheet is very helpful if you want to show large amount of data with sticky header and footer view.

 

Add below dependency in your pubspec.yaml file

sliding_sheet: ^0.5.0
 
 

Create Header View

Widget buildHeader(BuildContext context, SheetState state) {
return MyContainer(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 16),
colorShadow: Colors.black12,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(height: 8),
Text(
‘Football Players’,
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold
),
),
const SizedBox(height: 8),
],
),
);
}
 
 

Create Footer View

Widget buildFooter(BuildContext context, SheetState state) {
return Text(
‘WWW.CODINGWITHDHRUMIL.COM’,
style: TextStyle(
fontSize: 22,
),
);
}
 
 

Create Body Part

Widget buildBody(BuildContext context, SheetState state) {
final divider = Container(
height: 1,
color: Colors.grey.shade300,
);

return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
divider,
const SizedBox(height: 32),
buildListView(context),
const SizedBox(height: 32),
divider,
const SizedBox(height: 8),
],
);
}

Widget buildListView(BuildContext context) {
List<String> listFootballPlayers = [
‘Cristiano Ronaldo’,
‘Lionel Messi’,
‘Kevin De Bruyne’,
‘Neymar’,
‘Kylian MbappĂ©’,
‘Robert Lewandowski’,
‘Antoine Griezmann’,
‘Harry Kane’,
‘Mohamed Salah’,
‘Virgil van Dijk’,
‘Sergio Ramos’,
‘Paul Pogba’,
‘Eden Hazard’,
‘Raheem Sterling’,
‘Erling Haaland’
];

return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: listFootballPlayers.length,
itemBuilder: (context, i) {
final playerName = listFootballPlayers[i];

return Padding(
padding: const EdgeInsets.fromLTRB(56, 16, 0, 0),
child: Text(
playerName,
style: TextStyle(
fontSize: 28,
),
),
);
},
);
}

 
 

Create Custom View for Sliding Sheet Flutter

import ‘dart:math’;
import ‘package:flutter/material.dart’;

enum ShadowDirection {
topLeft,
top,
topRight,
right,
bottomRight,
bottom,
bottomLeft,
left,
center,
}

class MyContainer extends StatelessWidget {
final double borderRadius;
final BorderRadius customBorderRadius;
final EdgeInsets margin;
final EdgeInsets padding;
final Widget child;
final Color color;
final Color colorShadow;
final List<BoxShadow> listBoxShadows;
final double elevation;
final double height;
final double width;
final Border border;
final VoidCallback onTap;
final VoidCallback onLongPress;
final VoidCallback onDoubleTap;
final Color colorRipple;
final bool animate;
final Duration duration;
final BoxShape boxShape;
final AlignmentGeometry alignment;
final ShadowDirection shadowDirection;
const MyContainer({
Key key,
this.child,
this.border,
this.color = Colors.transparent,
this.borderRadius = 0.0,
this.elevation = 0.0,
this.colorRipple,
this.colorShadow = Colors.black12,
this.onTap,
this.onDoubleTap,
this.onLongPress,
this.height,
this.width,
this.margin,
this.customBorderRadius,
this.alignment,
this.listBoxShadows,
this.animate = false,
this.duration = const Duration(milliseconds: 200),
this.boxShape = BoxShape.rectangle,
this.shadowDirection = ShadowDirection.bottomRight,
this.padding = const EdgeInsets.all(0),
}) : super(key: key);

static const double WRAP = -1;
static const double EXPAND = -2;

bool get circle => boxShape == BoxShape.circle;

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final w = width == null || width == EXPAND ? double.infinity : width == WRAP ? null : width;
final h = height == EXPAND ? double.infinity : height;
final br = customBorderRadius ??
BorderRadius.circular(
boxShape == BoxShape.rectangle ? borderRadius : w != null ? w / 2.0 : h != null ? h / 2.0 : 0,
);

Widget content = Padding(
padding: padding,
child: child,
);

if (boxShape == BoxShape.circle || (customBorderRadius != null || borderRadius > 0.0)) {
content = ClipRRect(
borderRadius: br,
child: content,
);
}

content = Material(
color: Colors.transparent,
type: MaterialType.transparency,
shape: circle ? const CircleBorder() : RoundedRectangleBorder(borderRadius: br),
child: InkWell(
splashColor: onTap != null ? colorRipple ?? theme.splashColor : Colors.transparent,
customBorder: circle ? const CircleBorder() : RoundedRectangleBorder(borderRadius: br),
onTap: onTap,
onLongPress: onLongPress,
onDoubleTap: onDoubleTap,
child: content,
),
);

final List<BoxShadow> boxShadow = listBoxShadows ?? elevation != 0
? [
BoxShadow(
color: colorShadow ?? Colors.black12,
offset: shadowOffset(min(elevation / 5.0, 1.0)),
blurRadius: elevation,
spreadRadius: 0,
),
]
: const [];

final boxDecoration = BoxDecoration(
color: color,
borderRadius: circle ? null : br,
shape: boxShape,
boxShadow: boxShadow,
border: border,
);

return animate
? AnimatedContainer(
height: h,
width: w,
margin: margin,
alignment: alignment,
duration: duration,
decoration: boxDecoration,
child: content,
)
: Container(
height: h,
width: w,
margin: margin,
alignment: alignment,
decoration: boxDecoration,
child: content,
);
}

Offset shadowOffset(double ele) {
final ym = 5 * ele;
final xm = 2 * ele;
switch (shadowDirection) {
case ShadowDirection.topLeft:
return Offset(-1 * xm, -1 * ym);
break;
case ShadowDirection.top:
return Offset(0, -1 * ym);
break;
case ShadowDirection.topRight:
return Offset(xm, -1 * ym);
break;
case ShadowDirection.right:
return Offset(xm, 0);
break;
case ShadowDirection.bottomRight:
return Offset(xm, ym);
break;
case ShadowDirection.bottom:
return Offset(0, ym);
break;
case ShadowDirection.bottomLeft:
return Offset(-1 * xm, ym);
break;
case ShadowDirection.left:
return Offset(-1 * xm, 0);
break;
default:
return Offset.zero;
break;
}
}
}

 
 

Create Sliding Sheet Flutter

Widget buildSheet() {
return SlidingSheet(
duration: const Duration(milliseconds: 900),
controller: controller,
color: Colors.white,
shadowColor: Colors.black26,
elevation: 12,
maxWidth: 500,
cornerRadius: 16,
cornerRadiusOnFullscreen: 0.0,
closeOnBackdropTap: true,
closeOnBackButtonPressed: true,
addTopViewPaddingOnFullscreen: true,
isBackdropInteractable: true,
border: Border.all(
color: Colors.grey.shade300,
width: 3,
),
snapSpec: SnapSpec(
snap: true,
positioning: SnapPositioning.relativeToAvailableSpace,
snappings: const [
SnapSpec.headerFooterSnap,
0.6,
SnapSpec.expanded,
],
onSnap: (state, snap) {

},
),
parallaxSpec: const ParallaxSpec(
enabled: true,
amount: 0.35,
endExtent: 0.6,
),
body: Container(),
headerBuilder: buildHeader,
footerBuilder: buildFooter,
builder: buildBody,
);
}

 
 

Integrate Sliding Sheet

import ‘package:flutter/material.dart’;
import ‘package:sliding_sheet/sliding_sheet.dart’;
import ‘my_container.dart’;

class MySlidingSheet extends StatefulWidget {
@override
_MySlidingSheetState createState() => _MySlidingSheetState();
}

class _MySlidingSheetState extends State<MySlidingSheet> {

SheetController controller = SheetController();

bool tapped = false;
bool show = false;

@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: <Widget>[
Expanded(
child: buildSheet(),
),
],
),
);
}
}

 
 
 
sliding sheet flutter
 
 
 

Leave a Reply