Ayush Shekhar
Ayush Shekhar

Reputation: 1563

How can I customise the flexibleSpace property in SliverAppBar in Flutter?

Instead of using FlexibleSpaceBar in the flexibleSpace property of SliverAppBar I want to use a custom widget tree, when expanded, but upon scrolling, I want to display a custom text, and not the widget tree.

I have created a custom widget tree which shall be assigned to the flexibleSpace property, but I don't know how to display custom text on scrolling, and hide the widget tree.

SliverAppBar(
          expandedHeight: 180.0,
          backgroundColor: const Color(0xFF9e0118),
          iconTheme: IconThemeData(color: Colors.white),
          floating: true,
          pinned: true,
          flexibleSpace: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Container(
                  margin: EdgeInsets.only(top: 16.0),
                  padding: EdgeInsets.only(left: 32.0, right: 32.0),
                  child: Text(
                    'Some text',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        color: Colors.white,
                        fontFamily: 'PlayfairDisplay',
                        fontStyle: FontStyle.italic,
                        fontSize: 16.0),
                  )),
              Container(
                  margin: EdgeInsets.only(top: 16.0),
                  padding: EdgeInsets.only(left: 32.0, right: 32.0),
                  child: Text(
                    'some text',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        color: Colors.white,
                        fontFamily: 'PlayfairDisplay',
                        fontSize: 16.0),
                  )),
            ],
          ),
        ),

Upvotes: 9

Views: 28656

Answers (2)

Migalv
Migalv

Reputation: 702

To complete @westdabestdb answer, to make the title appear on scroll, it's really simple.

You just need to add the Animated Widget of you your choice and use the addListener from your scroll controller to switch a boolean. To find more Animated Widgets go to the official docs for Flutter Animated Widgets: https://flutter.dev/docs/development/ui/widgets/animation

Here is an example with an AnimatedOpacity Widget and the Parallax collapse mode which in my opinion work pretty well together.

class YourPage extends StatelessWidget {
  const YourPage({Key key}) : super(key: key);

  ScrollController _scrollController;
  bool _isScrolled = false;

  @override
  void initState() { 
    _scrollController = ScrollController();
    _scrollController.addListener(_listenToScrollChange);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: CustomScrollView(
          controller: _scrollController,
          slivers: <Widget>[
            SliverAppBar(
              expandedHeight: 144.0,
              pinned: true,
              forceElevated: true,
              ////////////////////////////////////
              // HERE IS THE PART TO BE ADDED
              title: AnimatedOpacity(
                duration: Duration(milliseconds: 300),
                opacity: _isScrolled ? 1.0 : 0.0,
                curve: Curves.ease,
                child: Text("YOUR TITLE HERE"),
              ),
              ////////////////////////////////////
              flexibleSpace: FlexibleSpaceBar(
                titlePadding: const EdgeInsets.only(bottom: 8.0),
                centerTitle: true,
                collapseMode: CollapseMode.parallax,
                background: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Container(
                        margin: EdgeInsets.only(top: 16.0),
                        padding: EdgeInsets.only(left: 32.0, right: 32.0),
                        child: Text(
                          'Some text',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                              color: Colors.white,
                              fontFamily: 'PlayfairDisplay',
                              fontStyle: FontStyle.italic,
                              fontSize: 16.0),
                        )),
                    Container(
                        margin: EdgeInsets.only(top: 16.0),
                        padding: EdgeInsets.only(left: 32.0, right: 32.0),
                        child: Text(
                          'some text',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                              color: Colors.white,
                              fontFamily: 'PlayfairDisplay',
                              fontSize: 16.0),
                        )),
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );
  }

// METHODS
  void _listenToScrollChange() {
    if (_scrollController.offset >= 48.0) {
      setState(() {
        _isScrolled = true;
      });
    } else {
      setState(() {
        _isScrolled = false;
      });
    }
  }
}

You will just have to play around with the values of the if in the _listenToScrollChange and the Duration of the animation to obtain the desired output.

Upvotes: 6

westdabestdb
westdabestdb

Reputation: 4638

You may want to wrap your widget tree inside a FlexibleSpaceBar widget and add your widget tree as background. I hope I understood your question right. Check this gif.

SliverAppBar(
      expandedHeight: 180.0,
      backgroundColor: const Color(0xFF9e0118),
      iconTheme: IconThemeData(color: Colors.white),
      floating: true,
      pinned: true,
      flexibleSpace: FlexibleSpaceBar(
        collapseMode: CollapseMode.pin,
        centerTitle: true,
        background: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Container(
                margin: EdgeInsets.only(top: 16.0),
                padding: EdgeInsets.only(left: 32.0, right: 32.0),
                child: Text(
                  'Some text',
                  textAlign: TextAlign.center,
                  style: TextStyle(
                      color: Colors.white,
                      fontFamily: 'PlayfairDisplay',
                      fontStyle: FontStyle.italic,
                      fontSize: 16.0),
                )),
            Container(
                margin: EdgeInsets.only(top: 16.0),
                padding: EdgeInsets.only(left: 32.0, right: 32.0),
                child: Text(
                  'some text',
                  textAlign: TextAlign.center,
                  style: TextStyle(
                      color: Colors.white,
                      fontFamily: 'PlayfairDisplay',
                      fontSize: 16.0),
                )),
          ],
        ),
      ),
    ),

Upvotes: 15

Related Questions