Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter How to check if Sliver AppBar is expanded or collapsed?

I am using a SliverAppBar in Flutter, with a background widget.

The thing is When it's expanded, the title and icons (leading and actions) should be white in order to be seen correctly, and when it's collapsed, they should be changed to black.

Any ideas on how I can get a bool out of it? Or other ways of resolving this problem.

Thank you.

class SliverExample extends StatefulWidget {   final Widget backgroundWidget;   final Widget bodyWidgets;    SliverExample({     this.backgroundWidget,     this.body,   });   @override   _SliverExampleState createState() => _SliverExampleState(); }  class _SliverExampleState extends State<SliverExample> {    // I need something like this   // To determine if SliverAppBar is expanded or not.   bool isAppBarExpanded = false;    @override   Widget build(BuildContext context) {      // To change the item's color accordingly     // To be used in multiple places in code     Color itemColor = isAppBarExpanded ? Colors.white : Colors.black;      // In my case PrimaryColor is white,     // and the background widget is dark      return Scaffold(       body: CustomScrollView(         slivers: <Widget>[           SliverAppBar(             pinned: true,             leading: BackButton(               color: itemColor, // Here             ),             actions: <Widget>[               IconButton(                 icon: Icon(                   Icons.shopping_cart,                   color: itemColor, // Here                 ),                 onPressed: () {},               ),             ],             expandedHeight: 200.0,             flexibleSpace: FlexibleSpaceBar(               centerTitle: true,               title: Text(                 'title',                 style: TextStyle(                   fontSize: 18.0,                   color: itemColor, // Here                 ),               ),               // Not affecting the question.                             background: widget.backgroundWidget,             ),           ),           // Not affecting the question.           SliverToBoxAdapter(child: widget.body),         ],       ),     );   } } 
like image 783
Sina Seirafi Avatar asked Nov 19 '18 10:11

Sina Seirafi


People also ask

How do you check if sliver AppBar is expanded or collapsed?

You can use SliverLayoutBuilder to get the current SliverConstraints and read its value, to easily detect how much scrolling has occurred. This is very similar to LayoutBuilder except it's operating in the sliver-world. If constraints. scrollOffset > 0 , that means the user has scrolled at least a little bit.

How do I use flexible space in AppBar flutter?

flexibleSpace field, a flexible space bar expands and contracts as the app scrolls so that the AppBar reaches from the top of the app to the top of the scrolling contents of the app. When using SliverAppBar. flexibleSpace, the SliverAppBar. expandedHeight must be large enough to accommodate the SliverAppBar.

What is silver AppBar in flutter?

SliverAppBar is a Material Design widget in flutter which gives scrollable or collapsible app-bar. The word Sliver is given to scrollable areas here. SliverAppBar basically gives us means to create an app-bar that can change appearance, blend in the background, or even disappear as we scroll.

How do I make my collapsing toolbar flutter?

In Android the CollapsingToolbar UI component is available within the design-support library, while in iOS there is no official UI component, but there are libraries that help us to do the same. In order to do the same in Flutter, we need to use the Widget called SliverAppBar together with FlexibleSpaceBar as a child.


2 Answers

You can use LayoutBuilder to get sliver AppBar biggest height. When biggest.height = MediaQuery.of(context).padding.top + kToolbarHeight, it actually means sliver appbar is collapsed.

Here is a full example, in this example MediaQuery.of(context).padding.top + kToolbarHeight = 80.0:

import 'package:flutter/material.dart';  void main() => runApp(MaterialApp(       home: MyApp(),     ));  class MyApp extends StatefulWidget {   @override   _MyAppState createState() => _MyAppState(); }  class _MyAppState extends State<MyApp> {   var top = 0.0;    @override   Widget build(BuildContext context) {     return Scaffold(         body: NestedScrollView(       headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {         return <Widget>[           SliverAppBar(               expandedHeight: 200.0,               floating: false,               pinned: true,               flexibleSpace: LayoutBuilder(                   builder: (BuildContext context, BoxConstraints constraints) {                 // print('constraints=' + constraints.toString());                 top = constraints.biggest.height;                 return FlexibleSpaceBar(                     centerTitle: true,                     title: AnimatedOpacity(                         duration: Duration(milliseconds: 300),                         //opacity: top == MediaQuery.of(context).padding.top + kToolbarHeight ? 1.0 : 0.0,                         opacity: 1.0,                         child: Text(                           top.toString(),                           style: TextStyle(fontSize: 12.0),                         )),                     background: Image.network(                       "https://images.unsplash.com/photo-1542601098-3adb3baeb1ec?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=5bb9a9747954cdd6eabe54e3688a407e&auto=format&fit=crop&w=500&q=60",                       fit: BoxFit.cover,                     ));               })),         ];       },body: ListView.builder(         itemCount: 100,         itemBuilder: (context,index){           return Text("List Item: " + index.toString());         },       ),     ));   } } 

Final result:

enter image description here

like image 129
Jack Sun Avatar answered Sep 19 '22 11:09

Jack Sun


You need to use ScrollController to achieve the desired effect

try this code

import 'package:flutter/material.dart';  void main() => runApp(MyApp());  class MyApp extends StatelessWidget {    // This widget is the root of your application.   @override   Widget build(BuildContext context) {     return MaterialApp(       title: 'Flutter Demo',       theme: ThemeData(         primarySwatch: Colors.blue,       ),       home: SliverExample(         bodyWidgets: Text(             'Hello Body gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg'),         backgroundWidget: Text('Hello Background'),       ),     );   } }  class SliverExample extends StatefulWidget {   final Widget backgroundWidget;   final Widget bodyWidgets;    SliverExample({     this.backgroundWidget,     this.bodyWidgets,   });    @override   _SliverExampleState createState() => _SliverExampleState(); }  class _SliverExampleState extends State<SliverExample> {    ScrollController _scrollController;   Color _theme ;    @override   void initState() {     super.initState();     _theme = Colors.black;      _scrollController = ScrollController()       ..addListener(         () => _isAppBarExpanded ?             _theme != Colors.white ?         setState(           () {             _theme = Colors.white;             print(                 'setState is called');           },         ):{}             : _theme != Colors.black ?         setState((){           print(               'setState is called');           _theme = Colors.black;         }):{},        );   }    bool get _isAppBarExpanded {     return _scrollController.hasClients &&         _scrollController.offset > (200 - kToolbarHeight);   }    @override   Widget build(BuildContext context) {     // To change the item's color accordingly     // To be used in multiple places in code     //Color itemColor = isAppBarExpanded ? Colors.white : Colors.black;      // In my case PrimaryColor is white,     // and the background widget is dark      return Scaffold(       body: CustomScrollView(         controller: _scrollController,         slivers: <Widget>[           SliverAppBar(             pinned: true,             leading: BackButton(               color: _theme, // Here             ),             actions: <Widget>[               IconButton(                 icon: Icon(                   Icons.shopping_cart,                   color: _theme, // Here                 ),                 onPressed: () {},               ),             ],             expandedHeight: 200.0,             flexibleSpace: FlexibleSpaceBar(               centerTitle: true,               title: Text(                 'title',                 style: TextStyle(                   fontSize: 18.0,                   color: _theme, // Here                 ),               ),               // Not affecting the question.               background: widget.backgroundWidget,             ),           ),           // Not affecting the question.           SliverToBoxAdapter(child: widget.bodyWidgets),         ],       ),     );   } } 

if you are not familiar with ? : notation you can use the following

_scrollController = ScrollController()       ..addListener(           (){             if(_isAppBarExpanded){               if(_theme != Colors.white){                 setState(() {                   _theme = Colors.white;                   print('setState is called with white');                 });               }             }else{               if(_theme != Colors.black){                 setState(() {                   _theme = Colors.black;                   print('setState is called with black');                 });               }             }           } 
like image 30
Saed Nabil Avatar answered Sep 19 '22 11:09

Saed Nabil