What is single child ScrollView in flutter

In a series of articles we’ve been discussing scrolling widgets. The SingleChildScrollView is another important addition to that series. It’s true that SingleChildScrollView is not like other scrolling widgets; nevertheless, it’s useful in some special cases.

Here, we’ll look into that speciality that a SingleChildScrollView possesses.

Let’s start with a screenshot first. So that, we can understand the topic. Moreover, we’ll understand why we need single child scroll view widget.

A Column without SingleChildScrollView
A Column without SingleChildScrollView

The above image shows an overflown error message.

Why is that so?

It happened because the Column widget cannot be scrolled. As a result, it gives us error. However, we can make this single Column widget scrollable with the help of SingleChildScrollView.

And we’ll also learn how the Single child scroll view widget comes to our help. It not only makes the single Column widget scrollable, but enhances the performance also.

How we can do it, we’ll see in a minute.

Let us take a look at the code snippet first. This is our data model.

class Student {
  final String id;
  final String name;
  final String imageUrl;

  Student({
    required this.id,
    required this.name,
    required this.imageUrl,
  });
}

/// adding id and images
List<Student> students = [
  Student(
    id: 's1',
    name: 'Json',
    imageUrl:
        'https://cdn.pixabay.com/photo/2018/09/11/19/49/education-3670453_960_720.jpg',
  ),
  Student(
    id: 's2',
    name: 'Limpi',
    imageUrl:
        'https://cdn.pixabay.com/photo/2016/11/29/13/56/asian-1870022_960_720.jpg',
  ),
  Student(
    id: 's3',
    name: 'Maria',
    imageUrl:
        'https://cdn.pixabay.com/photo/2017/09/21/13/32/girl-2771936_960_720.jpg',
  ),
];

Next, we’ll map the list and return the list items as child items inside Column widget.

Column(
                    children: students.map((e) {
                      return AllStudents(title: e.name, image: e.imageUrl);
                    }).toList(),

Since the number of child items are not large, we can fit SingleChildScrollView for wrapping the single Column widget.

However, if the number of child items are too large, consider using ListView constructors like ListView.builderListView.custom, and ListView.separated. These widgets create items visible on demand. That definitely saves system resources.

The problem with the above code is different. We’ve mapped a list of Student instances, and tried to return using single Column widget. But, the Column widget has not enough room to display the entire contents.

Hence, we’ve got the above error message. Moreover, there are several reasons for that. It might happen, because some devices have unusually small screens. Otherwise, one can also use the flutter app in landscape mode. That may throw an error.

The Column widget always tries to expand as big as it can. Subsequently, it results in a conflict.

To mitigate that conflict, in some special cases, we can wrap the Column widget with the SingleChildScrollView.

How do I use SingleChildScrollView in flutter?

The SingleChildScrollView gives its children infinite amount of space. However, if our child items are expected to fit on the screen, we cannot make our flutter app more performant using ListView or CustomScrollView. We can easily resolve the conflict using SingleChildScrollView.

On the contrary, if our child items are not supposed to fit the screen, then using the SingleChildScrollView could be expensive as far as the performance is concerned.

Let us see the second screenshot and after that we can discuss the code that resolves the conflict and helps us to avoid getting the overflown error message.

A Column with SingleChildScrollView
A Column with SingleChildScrollView

Now, the error message has gone, and the scroll direction takes us to the bottom viewport where we can view the last child element.

Let’s see the full code now.

import 'package:flutter/material.dart';

import 'package:flutter/foundation.dart';

class Student {
  final String id;
  final String name;
  final String imageUrl;

  Student({
    required this.id,
    required this.name,
    required this.imageUrl,
  });
}

/// adding id and images
List<Student> students = [
  Student(
    id: 's1',
    name: 'Json',
    imageUrl:
        'https://cdn.pixabay.com/photo/2018/09/11/19/49/education-3670453_960_720.jpg',
  ),
  Student(
    id: 's2',
    name: 'Limpi',
    imageUrl:
        'https://cdn.pixabay.com/photo/2016/11/29/13/56/asian-1870022_960_720.jpg',
  ),
  Student(
    id: 's3',
    name: 'Maria',
    imageUrl:
        'https://cdn.pixabay.com/photo/2017/09/21/13/32/girl-2771936_960_720.jpg',
  ),
];

class SingleChildScrollViewSample extends StatelessWidget {
  const SingleChildScrollViewSample({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Students Name',
      home: StudentsHomePage(),
    );
  }
}

class StudentsHomePage extends StatelessWidget {
  const StudentsHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Students Home Page'),
      ),
      body: DefaultTextStyle(
        style: Theme.of(context).textTheme.bodyText2!,
        child: LayoutBuilder(
          builder: (BuildContext context, BoxConstraints viewportConstraints) {
            return SingleChildScrollView(
              child: ConstrainedBox(
                constraints: BoxConstraints(
                  minHeight: viewportConstraints.maxHeight,
                ),
                child: IntrinsicHeight(
                  child: Column(
                    children: students.map((e) {
                      return AllStudents(title: e.name, image: e.imageUrl);
                    }).toList(),
                  ),
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

class AllStudents extends StatelessWidget {
  final String title;
  final String image;
  const AllStudents({
    Key? key,
    required this.title,
    required this.image,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          Container(
            padding: const EdgeInsets.all(
              5.0,
            ),
            margin: const EdgeInsets.all(
              5.0,
            ),
            child: Text(
              title,
              style: const TextStyle(
                fontFamily: 'Allison',
                fontSize: 80.0,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
          Image.network(
            image,
            fit: BoxFit.cover,
            width: 250,
            height: 250,
          ),
        ],
      ),
    );
  }
}

In the above code, we’ve used a LayoutBuilder. The layout builder widget obtains the size of the viewport.

However, to obtain the size of the viewport, we need the ConstrainedBox widget that sets the minimum height of the Column widget. Now, the rule of thumb is, the Column widget cannot be smaller than its BoxConstraints.minHeight.

As a result, the height of the Column widget gets bigger than the minimum height provided by the ConstrainedBox and the sum of the heights of the children.

To sum up, the SingleChildScrollView is not always preferable. But, to wrap a single widget for making it scrollable, it’s ideal

By the way, you may want to take a look at the other Scrolling Widgets, before we close down further reading on this topic.

We have a list below.

What is ListView Flutter? How do I use ListView in Flutter?

How do I use SingleChildScrollView in flutter?

What is GridView and how do you centre a GridView item in Flutter?

What is GridView builder in Flutter?

What is the grid view in Flutter?

What is GridView count in flutter?

What is GridView.extent in Flutter?

How do I make my collapsing toolbar flutter?

What is SliverGrid in flutter?

How to use CustomScrollView in Flutter?

How to use NestedScrollView in flutter?

How to use PageView in Flutter

What is PageView builder in flutter?

What is PageView custom in flutter?

How to use DraggableScrollableSheet

What is ListView builder in flutter

What is ListView custom

What is ListView flutter

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter

Comments

2 responses to “What is single child ScrollView in flutter”

  1. […] What is single child ScrollView in flutter November 19, 2021 […]

  2. […] a series of articles we’ve been discussing scrolling widgets. The SingleChildScrollView is another important addition to that series. It’s true that SingleChildScrollView is not like […]

Leave a Reply