People often prefer to use Flutter to achieve a dynamic and appealing user interface. As a native developer, achieving a similar experience across different platforms is quite challenging. That’s why Flutter is quite often used as the Frontend Framework. In this post, we will discuss another user interface element that is more functional than modern, the DraggableScrollableSheet
Widget.
Preview of DraggableScrollableSheet π
For beginners, it’s just a sheet that as the name suggests is draggable and the contents inside the sheet are scrollable. While I am not sure in what case you might like to use it, here are some cases where I used it.


Now that we have a visual idea of DraggableScrollableSheet
, let us see how to create one displayed on the left above. We will first begin by exploring its constructor.
Intro to DraggableScrollableSheet in Flutter π±βπ
As we know that everything in Flutter is a widget and so is the DraggableScrollableSheet
as per the definition, it is a sheet that resizes itself according to the drag gestures provided by the user. It has an initial, minimum, and maximum size. The constructor of DraggableScrollableSheet
looks like this:
const DraggableScrollableSheet(
{
Key? key,
double initialChildSize = 0.5,
double minChildSize = 0.25,
double maxChildSize = 1.0,
bool expand = true,
bool snap = false,
List<double>? snapSizes,
DraggableScrollableController? controller,
required ScrollableWidgetBuilder builder
}
)
Here, the parameters which are in bold are the ones that are often used while the others are for additional tweaking. In this tutorial, we will discuss and use the bolded parameters only.
initialChildSize
: This attribute defaults to0.5
, using this we define what should be the default size of the sheet.minChildSize
: This attribute defaults to0.25
, and defines the minimum size the sheet can have when the user tries to expand or shrink it. TheinitialChildSize
should always be greater or equal tominChildSize
.maxChildSize
: This attribute defaults to1.0
, and defines the maximum size the sheet can have.
Note: The above attributes values can only exist in the range (0.0 - 1.0)
builder
: This is the main attribute where we will pass our sheet widget. We get two parameters in the builder functionBuildContext
andScrollController
. We use theScrollController
to sync the scroll of the sheet with our content. Further, we will discuss the builder method as we build our demoDraggableScrollableSheet
.
Getting Started with our Demo App π

1. Setting up the background
In this tutorial, I will not discuss how to implement the design of the background. We are just interested in how to implement DraggableScrollableSheet
. So for the design of the base of the page, simply copy the code into a file by the name properties_page.dart
.
OR
If you do not care about the background of the application, you can simply use a colored container as a background and that would do perfectly well.
2. Creating our DraggableScrollableSheet
As a good practice, we will not write our code directly in the main.dart
for this example, I am simply creating another file home_page.dart
and our DraggableScrollableSheet
code will reside there. In home_page.dart
:
import 'package:draggable_scrollable_sheet/properties_page.dart';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Positioned.fill(
// This is the background page, which will be displayed behind the sheet.
// In case you don't have PropertyPage() simply use colored container.
child: PropertyPage(),
),
Positioned.fill(
child: _getDraggableScrollableSheet(),
),
],
),
);
}
//TODO: Define _getDraggableScrollableSheet()
}
Code Explanation:
- We used
Stack
to achieve a hierarchical layout, so that widgets can overlay over each other as we want the sheet to pan across the page. Note, that the widgets declared withinchildren
parameter in theStack
widget are displayed in the opposite order of declaring it. - Firstly, using
Positioned.fill
we covered the whole page using thePropertyPage
widget. - Then, using another
Positioned.fill
we cover thePropertyPage
with our own sheet widget. - For our sheet, we will create a function that returns our sheet. (You can alternatively use a separate widget to define the sheet).
Now, let’s see how we define, the _getDraggableScrollableSheet()
function:
_getDraggableScrollableSheet() {
return SizedBox.expand(
child: DraggableScrollableSheet(
minChildSize: 0.1,
maxChildSize: 0.8,
initialChildSize: 0.1,
builder: (BuildContext context, ScrollController scrollController) {
return SingleChildScrollView(
// Consuming the scrollController provided
controller: scrollController,
child: Container(
margin: EdgeInsets.only(top: 0.05 * getSize(context).height),
height: 0.75 * getSize(context).height,
width: double.infinity,
// Generic Designing of the sheet
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topRight: Radius.circular(30.0),
topLeft: Radius.circular(30.0),
),
boxShadow: [
BoxShadow(
blurRadius: 5.0,
spreadRadius: 20.0,
offset: const Offset(0.0, 5.0),
color: Colors.black.withOpacity(0.1),
)
],
color: Colors.white,
),
// Contents of the sheet
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20),
Row(
children: [
const Spacer(),
Container(
height: 4,
width: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.grey,
),
),
const Spacer(),
],
),
// Declare your sheet content widgets ahead
],
),
),
);
},
),
);
}
Code Explanation:
- Firstly we use the
SizedBox.expand
widget, as we want the sheet to expand as per the user interaction. So, to achieve this behavior we wrap theDraggableScrollableSheet
withSizedBox.expand
. - Then we declare the
DraggableScrollableSheet
Widget, where we pass arguments as explained above. In thebuilder
method we need to pass any scrollable widget, which should consume theScrollController
provided by the builder method. - As a generic design of the sheet, we use a horizontal grey container to achieve the horizontal grey bar, to represent that this sheet is pullable/draggable (shown below). Below them, you can define the contents of the sheet that should be visible when the sheet is extended.

3. Remarks on DraggableScrollableSheet
We have now successfully implemented DraggableScrollableSheet
and we can now experience the behavior we expect. From a UI point of view, this is just the starting point of DraggableScrollableSheet
, we can further add widgets inside the sheet which can be viewed once the sheet is extended. In case you are wondering how to put another scrollable inside the previously defined SingleChildScrollView
, you can do this:
SingleChildScrollView(
controller: scrollController,
child: Column(
children: [
// Other widgets ...
Expanded(
child: ListView(
// Ensure to use the same scrollController provided by the builder method.
controller: scrollController,
children: [...],
),
),
],
),
),
If you want to see an example of how to achieve it, I have linked a repository at the end of this post, you can get the code from the repository.
Conclusion π
In this post, we learned about DraggableScrollableSheet
and how to implement it in Flutter. We also created a demo application along the way so that we have an idea of the syntax and the arguments. I hope you were able to learn something from this short journey, looking ahead to seeing what great app you build with Flutter.
Next, you may check out these Flutter essential topics which I covered in detail:
If you have any queries you can comment below and I will be happy to help you. If you are new to Flutter check my post on how to install Flutter on windows?