I have been working on the Scroll of the page, and at the same time, doing these things:

  • Changing color of the AppBar background when scrolling
  • Changing the AppBar background to transparent when scrolled to the top

My code works fine, but the problem here is, it is laggy when it comes to smooth scrolling.

I have read about the flutter documentation, and found out, that, using setState() inside the addListener() is not the best practice you can follow.

I have tried searching more about it, but couldn't find an efficient solution.

Here is my code:

class HomePageState extends State<HomePage> {
  int _selectIndex = 0;
  bool isAppbarCollapsing = false;
  final ScrollController _homeController = new ScrollController();

  @override
  void initState() {
    super.initState();

    // for adding appbar background color change effect 
    // when scrolled
    _initializeController();
  }

  @override
  void dispose(){
    _homeController?.dispose();
    super.dispose();
  }

  void _initializeController(){
    _homeController.addListener(() {
      if(_homeController.offset == 0.0 && !_homeController.position.outOfRange){
        //Fully expanded situation
        if(!mounted) return;
        setState(() => isAppbarCollapsing = false);
      }
      if(_homeController.offset >= 9.0 && !_homeController.position.outOfRange){
        //Collapsing situation
        if(!mounted) return;
        setState(()  => isAppbarCollapsing = true);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
     return Scaffold(
       appBar: AppBar(
          // here is how I am changing the color
          backgroundColor: isAppbarCollapsing ? Colors.white.withOpacity(0.8) : Colors.transparent
       ),
       body: Container(
         height: MediaQuery.of(context).size.height,
         width: MediaQuery.of(context).size.width,
         child: ListView(
           controller: _homeController
         )
       )
     );
  }
}


Solution 1: Jagraj Singh

You can try making a new stateful widget which returns an appbar. Pass the scroll controller to that widget and apply listeners in that appbar widget and then perform setState in the appbar widget.

What this will do is instead of rebuilding the whole screen it'll just rebuild the appbar only.