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), ], ), ); } }
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.
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.
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.
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.
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:
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'); }); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With