How to use Flutter SingleChildScrollView Widget

Let’s understand the role of Flutter singleChildScrollView widget inside a Flutter app. We’ll first go through its theoretical part, then implement it by practically understanding its parameters with Flutter code examples.

What is Flutter singleChildScrollView Widget?

This widget is used to give a scrolling effect to its child. There are cases when the content we have on screen exceeds the screen width/height or you can say that exceeds its parent size so shows an overflow error. In these cases, the single child scroll view widget helps us by giving the child a scroll effect so even if the item size exceeds then still we can scroll it and see the whole content without any overflow.

Syntax

SingleChildScrollView(
        child: //here comes the child of single child scroll view
      )
This single child scroll view widget will be used to make its child widget scrollable. It’s child parameter takes a Flutter widget so we can pass any widget of Flutter we like or that meets our project requirements. In the later sections, we’ll explain other parameters of singleChildScroll view as well.

Parameters

  1. child
  2. padding
  3. scrollDirection
  4. reverse
  5. physics
  6. controller

Code examples to explain the use of singleChildScrollView Flutter Widget

Example 1:  child Parameter

Example 1.1: Column widget without singleChildScrollView

Column(
      children: [
        for (int i = 0; i < 10; i++)
          Container(
            margin: EdgeInsets.all(11),
            height: 71,
            width: double.infinity,
            color: Colors.purpleAccent,
          )
      ],
    )
flutter column overflow

Explanation

  1. First, I created a simple column widget.
  2. Then in its children list I specified a for loop and it will loop 10 times.
  3. After that, I used a simple Flutter container widget with some height, width, color, and some margin to give some space to the containers.
  4. Here, you can see that the size of items exceeds the screen’s height and an overflow error is seen on the screen. We can fix it by wrapping this column widget with a single child scroll view. See the below example.

Example 1.2: Column widget with singleChildScrollView

SingleChildScrollView(
      child: Column(
          // the data specified in the above example
              )
         )

flutter singlechildscrollview widget

Now you can see that the overflow is gone. I tried to scroll it and it’s scrolling perfectly fine. I just passed the column widget to the child parameter of Flutter single child scroll view and it’s now scrollable. Keep in mind that the scroll is only helpful when the items exceed their parent size.

Example 2: padding parameter of Flutter singleChildScrollView

 padding: EdgeInsets.all(80)
flutter singlechildscrollview padding
The parameter ‘padding’ specifies how much space should be allocated between the single child scroll view and its parent widget. In this case, I used the all() method and gave it a value of 80(a larger value to see the difference more visible). This method specifies that the space should be equal from all 4 sides(top, left, right, bottom). You can use other methods of EdgeInsets as well like only(), symmetric(), etc. We’ll explain these methods in more detail in our Flutter padding widget article.
If you want one or more sides to have a different value then you can use the copyWith() method as well like like this:
padding: EdgeInsets.all(80).copyWith(top: 0)
Here we won’t see any padding in the top because I just set it to 0. You can do it for other sides as well.

Example 3: scrollDirection parameter

SingleChildScrollView(

        scrollDirection: Axis.horizontal,

        child: Row(
          children: [
            for (int i = 1; i < 14; i++)
              Container(
                alignment: Alignment.center,
                margin: EdgeInsets.all(9),
                height: 71,
                width: 81,
                color: Colors.purpleAccent,
                child: Text(i.toString()),
              )
          ],
        ),
      )
flutter singlechildscrollview scroll direction axis horizontal
  • The scrollDirection parameter sets the direction in which the scroll will happen. By default, its set to vertical(top to bottom and vice versa).
  • In this example, I used a Flutter row widget and specified the container with for loop just like I’ve specified in the column widget. I also gave it a text widget to just simply show the index value too.
  • I’ve used the horizontal property of ‘Axis’ and passed it to the scrollDirection of singleChildScrollView widget. In the above, image you can see that I can now scroll the child widget which is row horizontally(left to right and vice versa).

Example 4: parameter ‘reverse’

 reverse: true
singlechildscrollview flutter reverse

This reverse parameter specifies that from which position(starting point) the scroll should start. By default, its set to false because it takes a Boolean value and it means that it’ll be from the start(in our case its left). But I passed it value ‘true’ which means it will start the scrolling from the end (right in our case because I set it to true).

To make things simple, just remember that it will start from the opposite direction when the reverse is true. You can see in the above image that the scroll starts from the end(right in our case).

Example 5: ‘physics’ parameter

This parameter deals with the user gestures(taps,scroll,behave) and how the single child scroll view should behave according to the gestures. Like what to do when the user try to scroll the items, what to do when the user finishes the end of scrolls and more.

Let’s understand the different behaviours with some classes of ‘ScrollPhysics‘ with code examples.

Example 5.1: AlwaysScrollableScrollPhysics() class

   physics: AlwaysScrollableScrollPhysics()
flutter singlechildscrollview physics
This class will make the child always respond to the user gestures even if the child size is not larger than its parent size. In the above image, I’ve only 2 items which size is not exceeding the width of screen but still if I try to scroll it, then it gives a bit of a scrolling response and it proves that its giving the reaction. The reason you are seeing it in center of screen is because I wrapped the singleChildScrollView with center widget.

Example 5.2: BouncingScrollPhysics() class

physics: BouncingScrollPhysics()
This will add a bouncing effect. When you scroll the items and you reach the edge then you will see a bouncing effect. It basically gives the edges a bouncing effect.

Example 5.3: NeverScrollableScrollPhysics() class

 NeverScrollableScrollPhysics()
This will remove the scroll effect from the child widget of singleChildScrollView. Although, you won’t see any oveflow if the items size is more than the parent size(in our case, its the size of the screen’s width). This is used when you have nested singleChildScrollViews inside a column/row and it’s wrapped with a parent single child scroll view and you only want the parent scroll effect for all of them. Just try it and you will understand this concept.

Example 6: singleChildScrollView inside a fixed height and width

Center(
      child: Container(
        height: 150,
        width: 150,
        decoration: BoxDecoration(color: Colors.purple, boxShadow: [
          BoxShadow(blurRadius: 5, spreadRadius: 1, color: Colors.grey)
        ]),
        child: SingleChildScrollView(
          child: Column(
            children: [
              for (int i = 1; i < 10; i++)
                Container(
                  alignment: Alignment.center,
                  margin: EdgeInsets.all(9),
                  height: 70,
                  width: 150,
                  color: Colors.purple.shade100,
                  child: Text(i.toString()),
                )
            ],
          ),
        ),
      ),
    )

Without singleChildScrollView

column widget flutter overflow height

With singleChildScrollView

flutter singlechildscrollview column widget

  • Here I have used a container with a height, width, color and some shadow for decoration and inside it I specified a simple column with items.
  • In the first image, I haven’t used single child scroll view and you can see an overflow when the items size exceeds the height of container.
  • While in the second image, I only wrapped the column widget with single child scroll view and now you can see that the error is gone and I can easily scroll the items inside container.
  • This was a simple example of how to can use this single child scroll view widget like this as well.

Example 6: controller parameter

class CustomScrollWidget extends StatefulWidget {
  @override
  _CustomScrollWidgetState createState() => _CustomScrollWidgetState();
}

class _CustomScrollWidgetState extends State<CustomScrollWidget> {

  final ScrollController _scrollController = ScrollController();
  bool _showScrollToTopButton = false; // For the floating action button

  @override
  void initState() {
    super.initState();
    // Listen to scroll changes
    _scrollController.addListener(() {
      print('Current scroll position: ${_scrollController.position.pixels}');
      // Show/hide the scroll-to-top button dependings on scroll position
      if (_scrollController.position.pixels > 100) {
        setState(() {
          _showScrollToTopButton = true;
        });
      } else {
        setState(() {
          _showScrollToTopButton = false;
        });
      }
    });
  }

  @override
  void dispose() {
    // Dispose the controller to free up resources
    _scrollController.dispose();
    super.dispose();
  }

  void _scrollToTop() {
    _scrollController.animateTo(
      0,
      duration: Duration(seconds: 1),
      curve: Curves.easeInOut,
    );
  }

  void _scrollToBottom() {
    _scrollController.animateTo(
      _scrollController.position.maxScrollExtent,
      duration: Duration(seconds: 1),
      curve: Curves.easeInOut,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('You can scroll up or down'),
        actions: [
          IconButton(
            icon: Icon(Icons.arrow_downward),
            onPressed: _scrollToBottom,
          ),
        ],
      ),

      body: SingleChildScrollView(
        controller: _scrollController, // Attach controller to the scroll view
        child: Column(
          children: List.generate(
            50,
            (index) => Padding(
              padding: EdgeInsets.symmetric(horizontal: 11, vertical: 4),
              child: ListTile(
                  tileColor: Colors.purple.shade700,
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(41)),
                  title: Text(
                    'Item $index',
                    style: TextStyle(color: Colors.white),
                  )),
            ),
          ),
        ),
      ),

      floatingActionButton: _showScrollToTopButton
          ? FloatingActionButton(
              onPressed: _scrollToTop,
              child: Icon(Icons.arrow_upward),
            )
          : null, // Show or hide FAB based on scroll position
    );
  }
}

flutter singlechildscrollview scroll controller

Explanation

Let me explain to you step by step how I implemented the scroll controller of single child scroll view to scroll up and down using custom buttons.

1. Define scrollController and boolean value

I define a ScrollController named _scrollController. This controller is used to listen to and control the scrolling behavior of the SingleChildScrollView. I also define a boolean variable _showScrollToTopButton to manage the visibility of a floating action button (FAB) that will allow the user to scroll back to the top by clicking the button.

2. initState Method

The initState method is called when the widget is first created. Here, I’ve added a listener to  _scrollController to monitor changes in the scroll position.

  • Listening to Scroll Changes: When the user scrolls, the listener will print the current scroll position in the console so you(the developer) can see the data by yourself. It also checks if the user has scrolled down more than 100 pixels. If it has then it sets _showScrollToTopButton to true (showing the button). If the scroll position is less than 100 pixels, it hides the button by setting _showScrollToTopButton to false.

3. dispose Method

The dispose method is called/triggered when the widget is removed from the widget tree. This method is important in our case because it helps free up resources by disposing of the _scrollController when it’s no longer needed.

4. Scroll to Top and Bottom Functions

Two helper functions are defined to help the user scroll to the top or bottom of the list:

  • _scrollToTop(): This function use the _scrollController.animateTo to smoothly scroll to the top (position 0) over duration of 1 second.
  • _scrollToBottom(): This function also make use of _scrollController.animateTo, but it scrolls to the maximum scroll extent (the bottom of the list), again over 1 second.

5. Building the UI

The build method defines the user interface(UI) for this specific widget:

  • Scaffold: It has the AppBar Widget, body, and a floating action button.
  • AppBar: Here, I specified a title and an icon in its actions parameter. When the user taps this icon, it calls the _scrollToBottom function to scroll to the bottom of the list.
  • SingleChildScrollView: It allows scrolling for its child widget. I’ve used the _scrollController to control this scroll view. The child is a Column that contains a list of items.
  • Column with List Items: Inside the Column widget, I’ve used List.generate to create 50 items. Each item is a ListTile wrapped in Padding widget so it has some space. The tiles have a purple background with rounded corners and white text(using the text widget and its textstyle) which I’ve done using its parameters.
  • Floating Action Button Visibility: If _showScrollToTopButton is true, then the floating action button will be shown. When clicked, it will call the _scrollToTop function to scroll back to the top. If _showScrollToTopButton is false, the FAB will hide or remain hidden if not shown already.

So in this way, we can specify custom buttons to scroll to the bottom or to the top using the controller parameter of Flutter singleChildScrollView.

Conclusion

Hope you now have a very well understanding of what the Flutter singleChildScrollView widget is and how you can use it in your app. You can play with its parameters to get your desired output. My recommendation is to use this widget in different scenarios so you can get used to its implementation with ease.

You can check out my other articles on Flutter app development for more information on other Flutter widgets and more. Thank you.

Leave a Comment

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