essayoub
essayoub

Reputation: 803

Flutter Fixed Button in CustomScrollView

How to make a button Fixed "Sticky" in bottom of CustomScrollView

How to achieve like the screenshot https://i.sstatic.net/RDCn9.png

Upvotes: 31

Views: 42810

Answers (5)

Lukas Pierce
Lukas Pierce

Reputation: 1259

Everything is quite simple. Use a column inside of which there will be an Expanded widget, inside of which there will be your scrollable main area

enter image description here

enter image description here

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: BottomFixedButtonExample(),
    );
  }
}

class BottomFixedButtonExample extends StatelessWidget {
  const BottomFixedButtonExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('App Bar'),
      ),
      body: Column(
        children: [
          Expanded(
            child: Container(
              decoration: BoxDecoration(border: Border.all(color: Colors.red, width: 10)),
              child: SingleChildScrollView(
                child: Column(
                  children: [
                    const Padding(
                      padding: EdgeInsets.all(10),
                      child: Text(
                        'The key thing is to wrap all your scrollable content in an Expanded widget.\n\n'
                        'As scrollable content you can use any scrolling widget such as ListView, SingleChildScrollView, CustomScrollView, ...',
                        style: TextStyle(fontSize: 16),
                      ),
                    ),
                    for (int i = 0; i < 20; i++)
                      Padding(
                        padding: const EdgeInsets.all(10),
                        child: TextFormField(
                          decoration: InputDecoration(
                            filled: true,
                            fillColor: Colors.white,
                            hintText: 'Input ${i + 1} - Try focus here',
                            border: const OutlineInputBorder(borderSide: BorderSide(width: 1)),
                          ),
                        ),
                      ),
                  ],
                ),
              ),
            ),
          ),
          SafeArea(
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: SizedBox(
                width: double.infinity,
                height: 44,
                child: ElevatedButton(
                  style: const ButtonStyle(
                    backgroundColor: MaterialStatePropertyAll(Colors.blue),
                    foregroundColor: MaterialStatePropertyAll(Colors.white),
                  ),
                  onPressed: () {
                    //
                  },
                  child: const Text('Save', style: TextStyle(fontSize: 16)),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Upvotes: 1

Anush Karki
Anush Karki

Reputation: 1

You can wrap up your scrollable widget with a Expanded widget. It will take up required space and leave the remaining for your button. Here's how i used to make the button stick both top & bottom.

Column(
            children: [
              //This is button 1
              Padding(
                padding: allPadding,
                child: GestureDetector(
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (context) => const myPage(),
                      ),
                    );
                  },
                  child: Container(
                    height: 40,
                    width: MediaQuery.of(context).size.width,
                    decoration: BoxDecoration(
                        color: Colors.green,
                        borderRadius: BorderRadius.circular(4)),
                    child: const Center(
                      child: Text(
                        "Button Name",
                        style: TextStyle(
                            color: Colors.white, fontWeight: FontWeight.bold),
                      ),
                    ),
                  ),
                ),
              ),
              
              //Here's my Scrollable widget
              Expanded(
                child: Center(
                  child: ListView.builder(
                    itemCount: provider.myList.length,
                    itemBuilder: (BuildContext context, index) {
                      return myCard(
                        provider: provider,
                        widgetTextStyle: widgetTextStyle,
                        index: index,
                      );
                    },
                  ),
                ),
              ),


             //this is the same button used as above
              Padding(
                padding: allPadding,
                child: GestureDetector(
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (context) => const myPage2(),
                      ),
                    );
                  },
                  child: Container(
                    height: 40,
                    width: MediaQuery.of(context).size.width,
                    decoration: BoxDecoration(
                        color: Colors.green,
                        borderRadius: BorderRadius.circular(4)),
                    child: const Center(
                      child: Text(
                        "Button 2",
                        style: TextStyle(
                            color: Colors.white, fontWeight: FontWeight.bold),
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),

Upvotes: -1

Phanindra
Phanindra

Reputation: 1378

Scaffold(
      body: 
      // list view here
      bottomNavigationBar: GestureDetector(
  child: Container(
    height: 50,
    width: 325,
    child: Center(
      child: Text(
        "title",
      ),
    onTap: (){},
  ),
);

this works for me as a work around

Upvotes: 0

EdHuamani
EdHuamani

Reputation: 1897

You can use floatingActionButton and floatingActionButtonLocation

exam:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

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

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        floatingActionButton: FloatingActionButton.extended(
          onPressed: () {},
          isExtended: true,
          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
          icon: Icon(Icons.supervised_user_circle),
          label: Text('Fixed Button'),
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
        body: CustomScrollView(
          slivers: <Widget>[
            const SliverAppBar(
              pinned: true,
              expandedHeight: 250.0,
              flexibleSpace: FlexibleSpaceBar(
                title: Text('Demo'),
              ),
            ),
            SliverGrid(
              gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                maxCrossAxisExtent: 200.0,
                mainAxisSpacing: 10.0,
                crossAxisSpacing: 10.0,
                childAspectRatio: 4.0,
              ),
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    alignment: Alignment.center,
                    color: Colors.teal[100 * (index % 9)],
                    child: Text('grid item $index'),
                  );
                },
                childCount: 20,
              ),
            ),
            SliverFixedExtentList(
              itemExtent: 50.0,
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    alignment: Alignment.center,
                    color: Colors.lightBlue[100 * (index % 9)],
                    child: Text('list item $index'),
                  );
                },
              ),
            ),
          ],
        ));
  }
}

Upvotes: 7

anmol.majhail
anmol.majhail

Reputation: 51206

One Way of Doing it - using - BottomNavigationBar

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>\[
          SliverAppBar(
            title: Text('Sliver App Bar'),
            expandedHeight: 125.0,
          ),
          SliverList(
              delegate: SliverChildBuilderDelegate((context, int) {
            return Text('Boo');
          }, childCount: 65)),
          SliverFillRemaining(
            child: Text('Foo Text'),
          ),
        \],
      ),
      bottomNavigationBar: Padding(
        padding: EdgeInsets.all(8.0),
        child: RaisedButton(
          onPressed: () {},
          color: Colors.blue,
          textColor: Colors.white,
          child: Text('Fixed Button'),
        ),
      ),
    );
  }][1]][1]

OutPut:

enter image description here

Upvotes: 69

Related Questions