flutterbuttonlayoutfixedstream-builder

flutter, ensure the elavated button stay at the bottom of the screen despite streambuilder built a lot of data


What im trying to do is showing a list of assignments and have buttons at the bottom to let the user to select which function they want but when the data becomes a lot and my buttons got push below the screen, i was hoping for the buttons to stay on the screen no matter how many data is generated, buttons will not get push down and the button does not block the visuals of the data, i got an image below to show that example at here

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:fyp/assignment/ViewComplete.dart';
import 'ReassignEmployee.dart';
import 'ViewAssigned.dart';
import 'ViewUnassigned.dart';

class assignmentPage extends StatefulWidget {
  const assignmentPage({Key? key}) : super(key: key);
  @override
  State<assignmentPage> createState() => _assignmentPageState();
}
class _assignmentPageState extends State<assignmentPage> {
  TextEditingController searchController = TextEditingController();
  String searchText = '';
  String id = '';
  CollectionReference allNoteCollection =
  FirebaseFirestore.instance.collection('Assignment');
  List<DocumentSnapshot> documents = [];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('View Assignment'),
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: [
            TextField(
              controller: searchController,
              onChanged: (value) {
                setState(() {
                  searchText = value;
                });
              },
              decoration: InputDecoration(
                hintText: 'Search...',
                prefixIcon: Icon(Icons.search),
              ),
            ),
            StreamBuilder(
              stream: allNoteCollection.snapshots(),
              builder: (ctx, streamSnapshot) {
                if (streamSnapshot.connectionState ==
                    ConnectionState.waiting) {
                  return Center(
                      child: CircularProgressIndicator());
                }
                documents = streamSnapshot.data!.docs;

                if (searchText.length > 0) {
                  documents = documents.where((element)
                  {
                    return
                      ( element.get('carPlate').toString().
                      toLowerCase().contains(searchText.toLowerCase()) ||
                          element.get('custName').toString().
                      toLowerCase().contains(searchText.toLowerCase())||
                          element.get('date').toString().
                          toLowerCase().contains(searchText.toLowerCase())||
                          element.get('employee').toString().
                          toLowerCase().contains(searchText.toLowerCase())||
                          element.get('id').toString().
                          toLowerCase().contains(searchText.toLowerCase())||
                          element.get('payment').toString().
                          toLowerCase().contains(searchText.toLowerCase())||
                          element.get('serviceName').toString().
                          toLowerCase().contains(searchText.toLowerCase())||
                          element.get('status').toString().
                          toLowerCase().contains(searchText.toLowerCase())||
                          element.get('timeEnd').toString().
                          toLowerCase().contains(searchText.toLowerCase())||
                          element.get('timeStart').toString().
                          toLowerCase().contains(searchText.toLowerCase())
                      );
                  }).toList();
                }
                return ListView.separated(
                  reverse: true,
                  shrinkWrap: true,
                  physics: NeverScrollableScrollPhysics(),
                  itemCount: documents.length,
                  separatorBuilder: (BuildContext context, int index) {
                    return Divider();
                  },
                  itemBuilder: (BuildContext context, int index) {
                    id = documents[index]['id'];
                    return ListTile(
                        contentPadding:
                        EdgeInsets.symmetric(horizontal: 0.0),
                        onTap: () {
                        },
                        title: Column(
                          children: <Widget>[
                            Text(documents[index]['carPlate']),
                            Text(documents[index]['custName']),
                            Text(documents[index]['date']),
                            Text(documents[index]['employee']),
                            Text(documents[index]['payment']),
                            Text(documents[index]['serviceName']),
                            Text(documents[index]['status']),
                            Text(documents[index]['timeStart']),
                            Text(documents[index]['timeEnd']),
                          ],
                        ),
                        trailing: Row(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            InkWell(
                              onTap: (){
                                Navigator.push(context,
                                    MaterialPageRoute(builder: (context) => ReassignEmployee(
                                      serviceName: documents[index]['serviceName'],
                                    carPlate: documents[index]['carPlate'],
                                    custName: documents[index]['custName'],
                                      date: documents[index]['date'],
                                      timeStart: documents[index]['timeStart'],
                                      timeEnd: documents[index]['timeEnd'],
                                      payment: documents[index]['payment'],
                                      status: documents[index]['status'],
                                      employee: documents[index]['employee'],
                                      id: documents[index]['id'],
                                    )));
                              },child: Icon(Icons.edit),
                            ),
                          ],
                        )
                    );
                  },
                );
              },
            ),
            ElevatedButton(
              onPressed: () async {
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => ViewUnassigned(id: id.toString(),)));
              },
              child: Text('Show unassigned'),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => ViewAssigned()));
              },
              child: Text('Show assigned'),
            ),
          ],
        ),
      ),
    );
  }
}

I have no idea how to do it, hope someone can guide me, really thanks a lot


Solution

  • You can use Stack and Positioned to pin buttons to the bottom of screen, like this:

    class assignmentPage extends StatefulWidget {
      const assignmentPage({Key? key}) : super(key: key);
      @override
      State<assignmentPage> createState() => _assignmentPageState();
    }
    
    class _assignmentPageState extends State<assignmentPage> {
      TextEditingController searchController = TextEditingController();
      String searchText = '';
      String id = '';
      CollectionReference allNoteCollection =
          FirebaseFirestore.instance.collection('Assignment');
      List<DocumentSnapshot> documents = [];
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('View Assignment'),
          ),
          body: Stack(
            children: [
              SingleChildScrollView(
                padding: const EdgeInsets.all(8.0),
                child: Column(
                  children: [
                    TextField(
                      controller: searchController,
                      onChanged: (value) {
                        setState(() {
                          searchText = value;
                        });
                      },
                      decoration: InputDecoration(
                        hintText: 'Search...',
                        prefixIcon: Icon(Icons.search),
                      ),
                    ),
                    StreamBuilder(
                      stream: allNoteCollection.snapshots(),
                      builder: (ctx, streamSnapshot) {
                        if (streamSnapshot.connectionState ==
                            ConnectionState.waiting) {
                          return Center(child: CircularProgressIndicator());
                        }
                        documents = streamSnapshot.data!.docs;
    
                        if (searchText.length > 0) {
                          documents = documents.where((element) {
                            return (element
                                    .get('carPlate')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()) ||
                                element
                                    .get('custName')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()) ||
                                element
                                    .get('date')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()) ||
                                element
                                    .get('employee')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()) ||
                                element
                                    .get('id')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()) ||
                                element
                                    .get('payment')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()) ||
                                element
                                    .get('serviceName')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()) ||
                                element
                                    .get('status')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()) ||
                                element
                                    .get('timeEnd')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()) ||
                                element
                                    .get('timeStart')
                                    .toString()
                                    .toLowerCase()
                                    .contains(searchText.toLowerCase()));
                          }).toList();
                        }
                        return ListView.separated(
                          reverse: true,
                          shrinkWrap: true,
                          physics: NeverScrollableScrollPhysics(),
                          itemCount: documents.length,
                          separatorBuilder: (BuildContext context, int index) {
                            return Divider();
                          },
                          itemBuilder: (BuildContext context, int index) {
                            id = documents[index]['id'];
                            return ListTile(
                                contentPadding:
                                    EdgeInsets.symmetric(horizontal: 0.0),
                                onTap: () {},
                                title: Column(
                                  children: <Widget>[
                                    Text(documents[index]['carPlate']),
                                    Text(documents[index]['custName']),
                                    Text(documents[index]['date']),
                                    Text(documents[index]['employee']),
                                    Text(documents[index]['payment']),
                                    Text(documents[index]['serviceName']),
                                    Text(documents[index]['status']),
                                    Text(documents[index]['timeStart']),
                                    Text(documents[index]['timeEnd']),
                                  ],
                                ),
                                trailing: Row(
                                  mainAxisSize: MainAxisSize.min,
                                  children: [
                                    InkWell(
                                      onTap: () {
                                        Navigator.push(
                                            context,
                                            MaterialPageRoute(
                                                builder: (context) =>
                                                    ReassignEmployee(
                                                      serviceName: documents[index]
                                                          ['serviceName'],
                                                      carPlate: documents[index]
                                                          ['carPlate'],
                                                      custName: documents[index]
                                                          ['custName'],
                                                      date: documents[index]
                                                          ['date'],
                                                      timeStart: documents[index]
                                                          ['timeStart'],
                                                      timeEnd: documents[index]
                                                          ['timeEnd'],
                                                      payment: documents[index]
                                                          ['payment'],
                                                      status: documents[index]
                                                          ['status'],
                                                      employee: documents[index]
                                                          ['employee'],
                                                      id: documents[index]['id'],
                                                    )));
                                      },
                                      child: Icon(Icons.edit),
                                    ),
                                  ],
                                ));
                          },
                        );
                      },
                    ),
                  ],
                ),
              ),
              Positioned(
                  bottom: 0,
                  left: 0,
                  right: 0,
                  child: Column(
                    children: [
                      ElevatedButton(
                        onPressed: () async {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => ViewUnassigned(
                                        id: id.toString(),
                                      )));
                        },
                        child: Text('Show unassigned'),
                      ),
                      ElevatedButton(
                        onPressed: () {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => ViewAssigned()));
                        },
                        child: Text('Show assigned'),
                      ),
                    ],
                  ))
            ],
          ),
        );
      }
    }