Home > Back-end >  How can I place a button in a scrollable list with ExpansionTiles in Flutter?
How can I place a button in a scrollable list with ExpansionTiles in Flutter?

Time:07-04

I have a scrolableView with x amount of ExpansionTiles, I need to place the 'Test' button on the bottom of the page, only if a number of tiles are fitting the screen or if they expand within the page, else to push the button off the screen.

import 'package:flutter/material.dart';

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

  List datas = [1, 2, 3, 4, 5, 6];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            children: [
              ListView.builder(
                physics: NeverScrollableScrollPhysics(),
                itemCount: datas.length,
                shrinkWrap: true,
                itemBuilder: (context, i) {
                  return ExpansionTile(
                      title: Text(
                        datas[i].toString(),
                      ),
                      children: List.generate(
                        datas.length,
                        (index) {
                          return Text(datas[index].toString());
                        },
                      ));
                },
              ),
              ElevatedButton(onPressed: () {}, child: Text('Test'))
            ],
          ),
        ),
      ),
    );
  }
}

Button should be on the bottom

Button is off-screen and in scrollable like it should

CodePudding user response:

The UX is a little tricky. It will be easy and get better performance using CustomScrollView.

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
          child: CustomScrollView(
        slivers: [
          SliverList(
            delegate: SliverChildListDelegate.fixed(
              [
                ...datas
                    .map((e) => ExpansionTile(
                        title: Text(
                          e.toString(),
                        ),
                        children: List.generate(
                          datas.length,
                          (index) {
                            return Text(datas[index].toString());
                          },
                        )))
                    .toList(),
              ],
            ),
          ),
          SliverFillRemaining(
            hasScrollBody: false,
            child: Align(
              alignment: Alignment.bottomCenter,
              child: ElevatedButton(
                onPressed: () {},
                child: const Text('Test'),
              ),
            ),
          )
        ],
      )),
    );
  }

The important thing is using SliverFillRemaining with hasScrollBody: false along with Align child.

More about CustomScrollView.

  • Related