How to create a persistent top and bottom on bottom sheet

Viewed 158

I want to create a flutter bottom sheet, and when I scroll it, the top and bottom parts of it will stay the same, only the contents part is moving. So, I can put the title on the top part of the bottom sheet, and buttons on the bottom part of the bottom sheet.

Here is my code for the floating action button and the model bottom sheet:

DateTime selectedDate = DateTime.now();

final marginForTasksAddingPanel =
  const EdgeInsets.only(left: 10.0, right: 10.0);
final sizedBoxForTasksAddingPanel = const SizedBox(height: 30.0);
final sizedBoxForTasksAddingPanelBetweenEachSection =
  const SizedBox(height: 15.0);



floatingActionButton: SizedBox(
      height: 70.0,
      width: 70.0,
      child: FittedBox(
        child: FloatingActionButton(
          onPressed: () => showModalBottomSheet(
            shape: const RoundedRectangleBorder(
              borderRadius: BorderRadius.vertical(
                top: Radius.circular(30.0),
              ),
            ),
            isScrollControlled: true,
            isDismissible: true,
            context: context,
            builder: (context) => tasksAddingPanel(),
          ),
          child: const Icon(
            Icons.add_outlined,
          ),
          backgroundColor: Colors.blue,
          elevation: 10.0,
        ),
      ),
    ),

Widget tasksAddingPanel() => DraggableScrollableSheet(
    expand: false,
    initialChildSize: 0.90,
    maxChildSize: 0.90,
    minChildSize: 0.90,
    builder: (context, scrollController) => Container(
      padding: const EdgeInsets.all(16.0),
      child: Stack(children: [
        ListView(
          controller: scrollController,
          children: [
            Container(
              margin: const EdgeInsets.only(top: 10.0, left: 10.0),
              child: const Text(
                'Add task',
                style: TextStyle(
                  fontSize: 23.0,
                ),
              ),
            ),
            sizedBoxForTasksAddingPanel,
            Container(
              margin: marginForTasksAddingPanel,
              child: const Text(
                'Title',
                style: TextStyle(
                  fontSize: 16.0,
                ),
              ),
            ),
            sizedBoxForTasksAddingPanelBetweenEachSection,
            Container(
              margin: marginForTasksAddingPanel,
              child: const TextField(
                decoration: InputDecoration(
                  hintText: 'Enter the name of the task',
                ),
              ),
            ),
            sizedBoxForTasksAddingPanel,
            Container(
              margin: marginForTasksAddingPanel,
              child: const Text(
                'Pick a date',
                style: TextStyle(
                  fontSize: 16.0,
                ),
              ),
            ),
            sizedBoxForTasksAddingPanelBetweenEachSection,
            Container(
              margin: marginForTasksAddingPanel,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  Text(
                    "${selectedDate.toLocal()}".split(' ')[0],
                    style: const TextStyle(
                        fontSize: 20, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(
                    width: 30.0,
                  ),
                  ClipRRect(
                    borderRadius: BorderRadius.circular(50.0),
                    child: ElevatedButton(
                      onPressed: () => _selectedDate(context),
                      // Refer step 3
                      child: const Text(
                        'Select date',
                        style: TextStyle(
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                    ),
                  ),
                ],
              ),
            ),
            sizedBoxForTasksAddingPanel,
            Container(
              margin: marginForTasksAddingPanel,
              child: const Text(
                'Label it',
                style: TextStyle(
                  fontSize: 16.0,
                ),
              ),
            ),
            sizedBoxForTasksAddingPanelBetweenEachSection,
            Container(
              margin: marginForTasksAddingPanel,
              child: GestureDetector(
                onTap: () {},
                child: Card(
                  color: Colors.blue,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(20.0),
                  ),
                  child: const ListTile(
                    title: Center(
                      child: Text(
                        'Personal',
                        style: TextStyle(
                          color: Colors.white,
                        ),
                      ),
                    ),
                    trailing: Icon(
                      Icons.arrow_downward_outlined,
                      color: Colors.white,
                    ),
                  ),
                ),
              ),
            ),
            sizedBoxForTasksAddingPanel,
            Container(
              margin: marginForTasksAddingPanel,
              child: const Text(
                'Set a reminder',
                style: TextStyle(
                  fontSize: 16.0,
                ),
              ),
            ),
            sizedBoxForTasksAddingPanelBetweenEachSection,
            Container(
              margin: marginForTasksAddingPanel,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Text(
                    "${selectedDate.toLocal()}".split(' ')[0],
                    style: const TextStyle(
                        fontSize: 20, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(
                    width: 30.0,
                  ),
                  SizedBox(
                    width: 150.0,
                    child: GestureDetector(
                      onTap: () => showCupertinoModalPopup(
                        context: context,
                        builder: (context) => SizedBox(
                          height: 200.0,
                          child: CupertinoDatePicker(
                            mode: CupertinoDatePickerMode.dateAndTime,
                            initialDateTime: selectedDate,
                            onDateTimeChanged: (DateTime newDate) {
                              setState(() {
                                selectedDate = newDate;
                              });
                            },
                          ),
                        ),
                      ),
                      child: Card(
                        color: Colors.blue,
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(20.0),
                        ),
                        child: const ListTile(
                          title: Center(
                            child: Icon(
                              Icons.alarm_add_outlined,
                              color: Colors.white,
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ]),
    ),
  ); 
1 Answers

You don't need DraggableScrollableSheet in this case, you can pass Container as showModalBottomSheet's builder and use

Column [TopWidget, Expanded<ListView>, BottomWidget ]

Test Widget

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

  xBottomSheet(BuildContext context) {
    showModalBottomSheet(
        context: context,
        isDismissible: true,
        isScrollControlled: true,
        shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.vertical(
            top: Radius.circular(30.0),
          ),
        ),
        builder: (context) => LayoutBuilder(
              builder: (context, constraints) {
                return Container(
                  height: constraints.maxHeight * .9,
                  decoration: const BoxDecoration(
                    color: Colors.cyanAccent,
                    borderRadius: BorderRadius.vertical(
                      top: Radius.circular(30.0),
                    ),
                  ),
                  child: Column(
                    children: [
                      Container(
                          height: 100,
                          alignment: Alignment.center,
                          width: double.infinity,
                          decoration: const BoxDecoration(
                            color: Colors.red,
                            borderRadius: BorderRadius.vertical(
                              top: Radius.circular(30.0),
                            ),
                          ),
                          child: Text("Top Bar")),
                      Expanded(
                        child: ListView(
                          children: List.generate(
                            44,
                            (index) => Container(
                              alignment: Alignment.center,
                              color: index.isEven
                                  ? Colors.deepPurple
                                  : Colors.green,
                              height: 100,
                              child: Text("Item $index"),
                            ),
                          ),
                        ),
                      ),
                      Container(
                          alignment: Alignment.center,
                          height: 100,
                          width: double.infinity,
                          color: Colors.amber,
                          child: Text("Bottom")),
                    ],
                  ),
                );
              },
            ));
  }

Related