Skip to content

Conversation

@Piinks
Copy link
Contributor

@Piinks Piinks commented Oct 8, 2019

Description

SliverAppBar.stretch

This PR introduces the ability to configure a stretch effect for a SliverAppBar when using ScrollPhysics that allow overscroll. (i.e. iOS's BouncingScrollPhysics).
This configuration also allows you to specify an amount of overscroll offset that will trigger a given callback function. The default triggering offset distance is 100.0.
This stretch features works with all of the SliverAppBar configurations - floating, pinned, snap, and default scrolling persistent headers all work with stretch.

FlexibleSpaceBar

Potential follow-up on this would be to add something along the lines of a stretchMode to FlexibleSpaceBar, similar to the collapseMode that is already provided.
The SliverAppBar changes alone would leave the FlexibleSpaceBar in a weird state when using the stretch feature, so I have added support here as well.
This support comes in the form of StretchModes, modeled after the CollapseModes that are already a part of FlexibleSpaceBar. Currently being added here are zoomBackground, blurBackground, and fadeTitle, all of which are in use in the animation below. Providing at least the zoomBackground stretch mode seems prudent since without it an app bar will stretch outside of the background. These stretch modes do not interfere with any of the collapse modes.

horizons

Code snippet behind this animation:

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: CustomScrollView(
          physics: BouncingScrollPhysics(),
          slivers: <Widget>[
            SliverAppBar(
              stretch: true,
              onStretchTrigger: () {print('hello!');},
              expandedHeight: 300.0,
              flexibleSpace: FlexibleSpaceBar(
                stretchModes: <StretchMode>[
                  StretchMode.zoomBackground,
                  StretchMode.blurBackground,
                  StretchMode.fadeTitle,
                ],
                centerTitle: true,
                title: const Text('Horizons'),
                background: Stack(
                  fit: StackFit.expand,
                  children: [
                    Image.network(
                      'https://images.unsplash.com/photo-1503803548695-c2a7b4a5b875?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80',
                      fit: BoxFit.cover,
                    ),
                    const DecoratedBox(
                      decoration: BoxDecoration(
                        gradient: LinearGradient(
                          begin: Alignment(0.0, 0.5),
                          end: Alignment(0.0, 0.0),
                          colors: <Color>[Color(0x60000000), Color(0x00000000)],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            SliverList(
              delegate: SliverChildListDelegate([
                ListTile(
                  leading: Icon(Icons.wb_sunny),
                  title: Text('Sunday'),
                  subtitle: Text('sunny, h: 80, l: 65'),
                ),
                ListTile(
                  leading: Icon(Icons.wb_sunny),
                  title: Text('Monday'),
                  subtitle: Text('sunny, h: 80, l: 65'),
                ),
                // ListTiles++
              ]
            ),
          ),
        ],
      ),
    )
  ));
}

More Custom Stretching!

While the stretch modes introduced here may not cover every possible stretch behavior, the changes to SliverAppBar alone make it much easier to implement your own custom behavior for stretching, as the proper constraints will be passed down from the SliverPersistentHeader to any of its children when stretch is true. For example, the Pesto demo of Flutter Gallery automatically adheres to the stretch, using a LayoutBuilder instead of a FlexibleSpaceBar. Shown here:

pesto

A follow-up PR will add animated illustrations to go along with sample code.

Related Issues

Fixes #27373

Tests

I added the following tests:

  • FlexibleSpaceBar stretch mode default zoomBackground
  • FlexibleSpaceBar stretch mode blurBackground
  • FlexibleSpaceBar stretch mode fadeTitle
  • FlexibleSpaceBar stretch mode ignored for non-overscroll physics
  • SliverAppBar - Stretch
    • fills overscroll
    • does not stretch without overscroll physics
    • default trigger offset
    • custom trigger offset
    • stretch callback not triggered without overscroll physics
    • asserts stretch != null
    • asserts reasonable trigger offset
  • SliverAppBar - Stretch, Pinned
    • fills overscroll
    • does not fill overscroll without proper physics
  • SliverAppBar - Stretch, Floating
    • fills overscroll
    • does not fill overscroll without proper physics
  • SliverAppBar - Stretch, Floating, Pinned
    • fills overscroll
    • does not fill overscroll without proper physics

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require Flutter developers to manually update their apps to accommodate your change?

  • No, this is not a breaking change.

@Piinks Piinks added c: new feature Nothing broken; request for a new capability framework flutter/packages/flutter repository. See also f: labels. f: scrolling Viewports, list views, slivers, etc. work in progress; do not review labels Oct 8, 2019
@fluttergithubbot fluttergithubbot added the f: material design flutter/packages/flutter/material repository. label Oct 8, 2019
@fluttergithubbot
Copy link
Contributor

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@Piinks Piinks removed the f: material design flutter/packages/flutter/material repository. label Oct 8, 2019
@Piinks Piinks changed the title [WIP] SliverAppBar - Configurable overscroll stretch with callback feature [WIP] SliverAppBar - Configurable overscroll stretch with callback feature & FlexibleSpaceBarSupport Oct 9, 2019
@Piinks Piinks changed the title [WIP] SliverAppBar - Configurable overscroll stretch with callback feature & FlexibleSpaceBarSupport [WIP] SliverAppBar - Configurable overscroll stretch with callback feature & FlexibleSpaceBar support Oct 9, 2019
@Piinks
Copy link
Contributor Author

Piinks commented Oct 10, 2019

cc/ @HansMuller FYI 🙂

@Piinks Piinks mentioned this pull request Oct 10, 2019
@fluttergithubbot fluttergithubbot added the f: material design flutter/packages/flutter/material repository. label Oct 17, 2019
@Piinks Piinks marked this pull request as ready for review October 18, 2019 22:28
@Piinks Piinks changed the title [WIP] SliverAppBar - Configurable overscroll stretch with callback feature & FlexibleSpaceBar support SliverAppBar - Configurable overscroll stretch with callback feature & FlexibleSpaceBar support Oct 18, 2019
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm no sliver expert but LGTM 👍

Just some small suggestions here and there.

@Piinks Piinks merged commit 11e1c24 into flutter:master Nov 5, 2019
@Piinks Piinks deleted the stretchyBar branch November 22, 2019 00:56
Inconnu08 pushed a commit to Inconnu08/flutter that referenced this pull request Nov 26, 2019
@arielfaur
Copy link

@Piinks Would this allow a Google Maps instance inside a SliverAppBar, instead of an image? I tried many approaches in the pass with no success.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

c: new feature Nothing broken; request for a new capability f: material design flutter/packages/flutter/material repository. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stretchy header effect

5 participants