Search code examples
flutterlistviewstream-builder

flutter/dart: streambuilder inside list view not scrolling


Is there anyway to making a streambuilder inside a list view scrollable?

I tried wrapping the form on a column widget but its not working out. none of the information is displayed on the screen for some reason.

here is a mini video of the issue:: https://youtu.be/_GIZkwzeH0Y

is there a different way to display this information?


    return Scaffold(
      appBar: AppBar(
        title: const Text('Job details'),
    
      ),
      body: FutureBuilder(
        future: createOrGetExistingJob(context),
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.done:
              _setupTextControllerListener();
              // at this point we want to start to listening for changes
              return Form(
                key: _formKey,
                child: ListView(
                  padding: const EdgeInsets.all(32.0),
                  children: [
                    getStateChevrons(_jobState),
                    const Divider(
                      height: 20,
                      thickness: 5,
                      indent: 0,
                      endIndent: 0,
                      color: Colors.blue,
                    ),
 
 //
 //
 //
 // Below is the streambuilder I would like to correctly display

                    getStateDependentButtons(context),
                    _jobDocumentId != null && _jobState != jobStateNew
                        ? StreamBuilder(
                            stream: _jobsService
                                .getJobApplication(_jobDocumentId as String),
                            builder: (context, snapshot) {
                              switch (snapshot.connectionState) {
                                case ConnectionState.waiting:
                                case ConnectionState.active:
                                  if (snapshot.hasData) {
                                    final allJobApplications = snapshot.data
                                        as Iterable<CloudJobApplication>;
                                    return JobApplicationsListView(
                                      jobApplications: allJobApplications,
                                      onTap: (job) {
                                        Navigator.of(context).pushNamed(
                                          myJobApplicationsRoute,
                                          arguments: job,
                                        );
                                      },
                                    );
                                  } else {
                                    return const CircularProgressIndicator();
                                  }
                                default:
                                  return const CircularProgressIndicator();
                              }
                            },
                          )
                        : const Text(
                            'Once job is submitted, job applications will be available')
                  ]
                      .map((child) => Padding(
                            padding: EdgeInsets.symmetric(vertical: 8.0),
                            child: child,
                          ))
                      .toList(),
                ),
              );

            default:
              return const CircularProgressIndicator();
          }
        },
      ),
      //
      //
    );
  
  

Here is what jobApplicationListView looks like::

import 'package:flutter/material.dart';
import '../../services/cloud/cloud_job_application.dart';
import '/services/cloud/cloud_job.dart';
import '/utilities/dialogs/delete_dialog.dart';
/*
source: https://www.youtube.com/watch?v=VPvVD8t02U8&t=59608s
class creation :: 22:02:54
 */

typedef JobCallback = void Function(CloudJobApplication jobApplication);

class JobApplicationsListView extends StatelessWidget {
  final Iterable<CloudJobApplication>
      jobApplications; // list of jobApplications
  //final JobCallback onDeleteJob;
  final JobCallback onTap;

  const JobApplicationsListView({
    Key? key,
    required this.jobApplications,
    //required this.onDeleteJob,
    required this.onTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      shrinkWrap: true,
      itemCount: jobApplications.length,
      itemBuilder: (context, index) {
        final jobApplication = jobApplications.elementAt(index);

        return ListTile(
          onTap: () {
            onTap(jobApplication);
          },
          title: Text(
            jobApplication.jobApplicationDescription,
            maxLines: 1,
            softWrap: true,
            overflow: TextOverflow.ellipsis,
          ),
          trailing: IconButton(
            onPressed: () async {
              final shouldDelete = await showDeleteDialog(context);
              if (shouldDelete) {
                "onDeleteJob(job)";
              }
            },
            icon: const Icon(Icons.delete),
          ),
        );
      },
    );
  }
}

Solution

  • On your JobApplicationsListView's ListView.builder( set physics: NeverScrollableScrollPhysics(), The parent already handling scroll event.

      @override
      Widget build(BuildContext context) {
        return ListView.builder(
          physics: NeverScrollableScrollPhysics(),
          itemCount: jobApplications.length,
          itemBuilder: (context, index) {
            final jobApplication = jobApplications.elementAt(index);
    
    

    Also you can try with primary: false, on it.

    Or you can use Column widget instead.