Skip to content
FlutterDocs

How to add ʺScroll Back to Topʺ Button in Flutter App

Verified Solution Tested on Flutter 3.47.7 • Dart 3.13.5
Jump to Updated Flutter Example ↓

In this example, we are going to show you the way to add the “Scroll back to top” button with fade in/fade out animation during the show or hide. You can use this Flutter app example in your project. See the code below:

The output of this example:

How to add ʺScroll Back to Topʺ Button in Flutter App screenshot

Flutter App Example with “Scroll Back to Top” Button:

import 'package:flutter/material.dart';

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

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

class Home extends  StatefulWidget {
  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  ScrollController scrollController = ScrollController();
  bool showbtn = false;

  List<String> countries = ["USA", "United Kingdom", "China", "Russia", "Brazil",
                              "India", "Pakistan", "Nepal", "Bangladesh", "Sri Lanka",
                              "Japan", "South Korea", "Mongolia"];

  @override
  void initState() {
    scrollController.addListener(() { //scroll listener 
        double showoffset = 10.0; //Back to top botton will show on scroll offset 10.0

        if(scrollController.offset > showoffset){
              showbtn = true;
              setState(() {
                //update state 
              });
        }else{
             showbtn = false;
              setState(() {
                //update state 
              });
        }
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
         appBar: AppBar(
            title: Text("Scroll Back to Top Button"),
            backgroundColor: Colors.redAccent
         ),
         floatingActionButton: AnimatedOpacity(
           duration: Duration(milliseconds: 1000),  //show/hide animation
           opacity: showbtn?1.0:0.0, //set obacity to 1 on visible, or hide
           child: FloatingActionButton( 
              onPressed: () {  
                 scrollController.animateTo( //go to top of scroll
                   0,  //scroll offset to go
                   duration: Duration(milliseconds: 500), //duration of scroll
                   curve:Curves.fastOutSlowIn //scroll type
                  );
              },
              child: Icon(Icons.arrow_upward),
              backgroundColor: Colors.redAccent,
           ), 
         ),
         body: SingleChildScrollView( 
                  controller: scrollController, //set controller
                  child:Container(
                    child:Column(
                      children: countries.map((country){
                          return Card( 
                            child:ListTile(
                                title: Text(country)
                            )
                          );
                      }).toList(),
                  )
              )
          )
    );
  } 
}

You can also use ListView() widget. In this example, We have added the scroll change listener and got Scroll position offset, and used it to make the “Scroll Back to Top” button. You can add Scroll bar on SingleChildScrollView widget in this example.

Output is shown above. This is the way you can add the “Scroll Back to Top” button in Flutter App. For managing long content views, explore scrollable ListView navigation and implementing FloatingActionButton widgets in Flutter.

Updated Flutter Example
SDK: Flutter 3.47.7 • Dart 3.13.5 Verified on Flutter 3.47.7 (Stable)

Updated Flutter Example

ScrollController & Animated Floating Action Button Architecture

Key Implementation Details & Modern Differences:

  • Animated Visibility Transitions: Uses AnimatedScale to gracefully scale the floating action button in and out based on scroll offset thresholds without abrupt UI popping.
  • Smooth Physics Animation: Calls ScrollController.animateTo(0, duration: ..., curve: Curves.easeInOut) to provide fluid, high-frame-rate scrolling rather than instant jumps.
  • Safe Lifecycle Disposal: Removes the scroll listener and disposes ScrollController in dispose() to prevent native platform resource leaks.
Updated Flutter Example Code
import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(home: ModernScrollToTopDemo()));
}

class ModernScrollToTopDemo extends StatefulWidget {
  const ModernScrollToTopDemo({super.key});

  @override
  State<ModernScrollToTopDemo> createState() => _ModernScrollToTopDemoState();
}

class _ModernScrollToTopDemoState extends State<ModernScrollToTopDemo> {
  final ScrollController _scrollController = ScrollController();
  bool _showBackToTop = false;

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_handleScroll);
  }

  void _handleScroll() {
    if (_scrollController.offset >= 300 && !_showBackToTop) {
      setState(() => _showBackToTop = true);
    } else if (_scrollController.offset < 300 && _showBackToTop) {
      setState(() => _showBackToTop = false);
    }
  }

  void _scrollToTop() {
    _scrollController.animateTo(
      0,
      duration: const Duration(milliseconds: 400),
      curve: Curves.easeInOut,
    );
  }

  @override
  void dispose() {
    _scrollController.removeListener(_handleScroll);
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Scroll Back to Top Architecture')),
      body: ListView.builder(
        controller: _scrollController,
        itemCount: 50,
        itemBuilder: (context, index) {
          return ListTile(
            leading: CircleAvatar(child: Text('${index + 1}')),
            title: Text('Feed Element Item #$index'),
            subtitle: const Text('Material 3 Dynamic List Scrolling'),
          );
        },
      ),
      floatingActionButton: AnimatedScale(
        scale: _showBackToTop ? 1.0 : 0.0,
        duration: const Duration(milliseconds: 200),
        child: FloatingActionButton.small(
          onPressed: _showBackToTop ? _scrollToTop : null,
          tooltip: 'Scroll to Top',
          child: const Icon(Icons.arrow_upward),
        ),
      ),
    );
  }
}
Document History & Archival Record

Original reference snapshot archived June 3, 2023. Updated working solution verified on modern Flutter & Dart SDKs.