DraggableScrollableSheet in Flutter

DraggableScrollableSheet in Flutter

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.

The application we will build
WallDust Application

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.

  1. initialChildSize: This attribute defaults to 0.5, using this we define what should be the default size of the sheet.
  2. minChildSize: This attribute defaults to 0.25, and defines the minimum size the sheet can have when the user tries to expand or shrink it. The initialChildSize should always be greater or equal to minChildSize.
  3. maxChildSize: This attribute defaults to 1.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)
  1. builder: This is the main attribute where we will pass our sheet widget. We get two parameters in the builder function BuildContext and ScrollController. We use the ScrollController to sync the scroll of the sheet with our content. Further, we will discuss the builder method as we build our demo DraggableScrollableSheet.

Getting Started with our Demo App πŸ“—

Image showing DraggableScrollableSheet in Flutter.
Design we will create

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:

  1. 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 within children parameter in the Stack widget are displayed in the opposite order of declaring it.
  2. Firstly, using Positioned.fill we covered the whole page using the PropertyPage widget.
  3. Then, using another Positioned.fill we cover the PropertyPage with our own sheet widget.
  4. 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:

  1. 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 the DraggableScrollableSheet with SizedBox.expand.
  2. Then we declare the DraggableScrollableSheet Widget, where we pass arguments as explained above. In the builder method we need to pass any scrollable widget, which should consume the ScrollController provided by the builder method.
  3. 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.
Image showing Empty DraggableScrollableSheet in Flutter.
Code Visual Explaination

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?

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
PostgreSQL-DB-HA-Patroni

How to Setup PostgreSQL High Availability with Patroni – Complete Guide

Next Post
Deploy, Host React app to GitHub Pages Featured Image

How to Host your React App on GitHub Pages

Related Posts