What is ListView custom

We’ve already learned that a ListView is a widget that arranges a scrollable list of widgets linearly. Moreover, we can construct ListView using four ways. We’ve seen two ListView constructors in our previous sections. ListView.builder and ListView.separated constructors play different roles in building a scrollable, linear array of widgets.

However, with a custom child model a ListView can control the algorithm used to estimate the size of children that are not actually visible.

The ListView.custom constructor is not like other two constructors. It takes a SliverChildDelegate, which provides the ability to customise additional aspects of the child model.

In this section we’ll see how we can use ListView.custom constructor to display a list of Student instances, using text and image. Moreover, we can also use a method to reverse the list, by changing the state of our UI.

Whenever, we discuss the scrolling widgets or slivers, we must remember that we need to preserve the state of child elements when they are scrolled in and out of view,

There are several options available, whatsoever. But, at present we will use provider package to manage the state.

How do I create a ListView with image and text in flutter?

Certainly, we can create a ListView with image and text in flutter with either ListView.builder and ListView.separated constructors. But, we can use ListView.custom constructor with a required parameter SliverChildDelegate childrenDelegate that helps us to customise the child elements.

To understand this mechanism, let’s consider a model class of students that will have id, name and an image property. Along with these properties, we’ve also added a method that will reverse the list on demand.

import 'package:flutter/foundation.dart';

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

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

class Students with ChangeNotifier {
  /// 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',
    ),
  ];

  void reverse() {
    students = students.reversed.toList();
    notifyListeners();
  }
}

Now, we’re going to take a look at the required parameter of ListView.custom constructor, which plays a very important role in building children.

child: ListView.custom(
/// required
          childrenDelegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) {
              return ChangeNotifierProvider.value(
                value: students[index],
...
// the code is incomplete for brevity
// you'll get the full code below

The childrenDelegate is the required parameter that is nothing but a delegate, which supplies children for slivers. Now, as a result, rather than receiving their children as an explicit List, they receive their children using a SliverChildDelegate.

Consequently, we can lay out the list now, using SliverChildListDelegate. Based on the existing widgets, visible children elements are created. Or, we can use SliverChildBuilderDelegate that provides widgets.

We’ve used the SliverChildBuilderDelegate, that passes context and index of the list items. While doing that it builds child elements on demand.

Let’s see the full code snippet now.

import 'package:flutter/material.dart';
import 'package:flutter_artisan/models/student.dart';
import 'package:provider/provider.dart';

class ListViewCustomSample extends StatelessWidget {
  const ListViewCustomSample({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) {
    final students = Provider.of<Students>(context).students;
    return Scaffold(
      appBar: AppBar(
        title: const Text('Students Home Page'),
      ),
      body: SafeArea(
        child: ListView.custom(
          childrenDelegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) {
              return ChangeNotifierProvider.value(
                value: students[index],
                child: Center(
                  child: Column(
                    children: [
                      Container(
                        padding: const EdgeInsets.all(5),
                        child: Text(
                          students[index].name,
                          style: const TextStyle(
                            fontFamily: 'Allison',
                            fontSize: 30,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ),
                      Image.network(
                        students[index].imageUrl,
                        fit: BoxFit.cover,
                      ),
                    ],
                  ),
                ),
              );
            },
            childCount: students.length,
          ),
        ),
      ),
      bottomNavigationBar: BottomAppBar(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              padding: const EdgeInsets.all(10),
              child: TextButton(
                onPressed: () => context.read<Students>().reverse(),
                child: const Text(
                  'Reverse students',
                  style: TextStyle(
                    fontFamily: 'Allison',
                    fontSize: 30,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

When we run the app, as usual the first student instance is created and being displayed on the screen.

ListView custom child items
ListView custom child items

At the bottom, the bottom navigation bar allows us to use a Text Button to reverse the list.

If we click the button, the list of student instances is reversed.

We’ve used latest provider package that helps us to notify listeners and that reverse the list for us.

 TextButton(
                onPressed: () => context.read<Students>().reverse(),
                child: const Text(
                  'Reverse students',
                  style: TextStyle(
                    fontFamily: 'Allison',
                    fontSize: 30,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
...

As a result, the last student instance comes up at the top.

ListView custom child items reversed
ListView custom child items reversed

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 separated

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter

Comments

2 responses to “What is ListView custom”

  1. […] four methods. We’ve already seen how we can use ListView by constructors like ListView.builder, ListView.custom, and […]

  2. […] of child items are too large, consider using ListView constructors like ListView.builder, ListView.custom, and ListView.separated. These widgets create items visible on demand. That definitely saves […]

Leave a Reply