Search code examples
flutterdartflutter-layout

How to handle ListView scroll direction


I have a dummy list of items I want to show a floating action button in swip up direction and hide it in down direction. how can I implement this functionality ?

class _MyHomePageState extends State<MyHomePage> {
  bool upDirection = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Container(
          child: Row(
            children: <Widget>[
              Expanded(
                  child: ListView.builder(
                    itemCount: 100,
                    itemBuilder: (context,index){
                      return ListTile(
                        title: Text(index.toString()),
                      );
                    },
                  ),
              )
            ],
          ),
        ),
      ),
      floatingActionButton:upDirection==true?FloatingActionButton(onPressed: (){},):Container() ,
    );
  }
}

Solution

  • Screenshot:

    enter image description here

    All you need is a NotificationListener.onNotification callback:

    NotificationListener<UserScrollNotification>(
      onNotification: (notification) {
        final ScrollDirection direction = notification.direction;
        return true;
      },
      child: ListView.builder(
        itemCount: 100,
        itemBuilder: (_, i) => ListTile(title: Text('$i')),
      ),
    )
    

    Full code:

    bool _visible = true;
      
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        floatingActionButton: AnimatedOpacity(
          duration: Duration(milliseconds: 400),
          opacity: _visible ? 1 : 0,
          child: FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: () {},
          ),
        ),
        body: NotificationListener<UserScrollNotification>(
          onNotification: (notification) {
            final ScrollDirection direction = notification.direction;
            setState(() {
              if (direction == ScrollDirection.reverse) {
                _visible = false;
              } else if (direction == ScrollDirection.forward) {
                _visible = true;
              }
            });
            return true;
          },
          child: ListView.builder(
            itemCount: 100,
            itemBuilder: (_, i) => ListTile(title: Text('$i')),
          ),
        ),
      );
    }