shiiboun
shiiboun

Reputation: 63

Scroll animation like yelp app in flutter

I'm trying to make a CustomScrollView similar to this:

yelp app

I'm using a SliverAppBar but it seems that it is not the right way. My code so far:

CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            expandedHeight: 340,
            pinned: true,
            flexibleSpace: FlexibleSpaceBar(
              background: BackgroundImageWidget(),
              centerTitle: true,
              //  title: Text("Search by cities or activitry in Kreis Kleve"),
              title: SearchButtonWidget(),
              ),
            ),
          ),
          SliverList(...) 

What I get:

my app

I cant figure out why the SearchButtonWidget is so huge at first. When it's shrinked it has the right size. Is sliverAppBar with fliexibleSpace even the right approach?

Edit: can someone also tell me how to make the search button overlapping with the widget below? I guess sliverAppBar can't do that.

Edit 2: maybe it's a white background added under the image. I need to investigate this.

Upvotes: 1

Views: 223

Answers (1)

Nardeepsinh Vaghela
Nardeepsinh Vaghela

Reputation: 978

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        top: true,
        child: CustomScrollView(
          slivers: <Widget>[
            SliverPersistentHeader(
              delegate: MySliverAppBar(
                  expandedHeight: 250,
                  title: Container(
                    margin: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
                    decoration: BoxDecoration(
                        color: Colors.grey[200],
                        borderRadius: BorderRadius.all(Radius.circular(5.0))),
                    child: Row(children: <Widget>[
                      Padding(
                        padding: EdgeInsets.only(left: 20.0, right: 10.0),
                        child: Icon(Icons.search),
                      ),
                      Expanded(
                        child: TextFormField(
                          keyboardType: TextInputType.text,
                          textInputAction: TextInputAction.done,
                          cursorColor: Colors.black,
                          autofocus: false,
                          decoration: InputDecoration(
                              filled: true,
                              fillColor: Colors.transparent,
                              contentPadding: EdgeInsets.symmetric(
                                  vertical: 10, horizontal: 15),
                              hintText: "Search",
                              border: InputBorder.none,
                              disabledBorder: OutlineInputBorder(
                                borderSide:
                                    new BorderSide(color: Colors.transparent),
                                borderRadius: new BorderRadius.circular(2),
                              ),
                              focusedBorder: OutlineInputBorder(
                                borderSide:
                                    new BorderSide(color: Colors.transparent),
                                borderRadius: new BorderRadius.circular(2),
                              )),
                        ),
                      )
                    ]),
                  )),
              pinned: true,
            ),
            SliverList(
                delegate: SliverChildBuilderDelegate((context, index) {
              return Container(
                  child: ListTile(
                title: Text("${index}a"),
              ));
            }, childCount: 25))
          ],
        ),
      ),
    );
  } 

.

class MySliverAppBar extends SliverPersistentHeaderDelegate {
  final double expandedHeight;
  final Widget title;

  MySliverAppBar({@required this.expandedHeight, this.title});

  final _avatarMarginTween = EdgeInsetsTween(
      begin: EdgeInsets.only(bottom: 20),
      end: EdgeInsets.only(
        bottom: 0.0,
      ));

  final _searchMarginTween = EdgeInsetsTween(
      begin: EdgeInsets.only(bottom: 0),
      end: EdgeInsets.only(bottom: 8,));
  final _avatarAlignTween =
      AlignmentTween(begin: Alignment.bottomCenter, end: Alignment.center);

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    double tempVal = 75 * maxExtent / 100;
    final progress =  shrinkOffset > tempVal ? 1.0 : shrinkOffset / tempVal;
    final avatarMargin = _avatarMarginTween.lerp(progress);
    final searchMargin = _searchMarginTween.lerp(progress);
    final searchAlignment = progress > 0.8 ? _avatarAlignTween.lerp(progress) : _avatarAlignTween.lerp(0);

    return Stack(
      fit: StackFit.expand,
      overflow: Overflow.visible,
      children: <Widget>[
        Padding(
          padding: avatarMargin,
          child: Image.network(
            "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
            fit: BoxFit.cover,
          ),
        ),
        Center(
          child: Opacity(
            opacity: shrinkOffset / expandedHeight > 0.7 ? shrinkOffset / expandedHeight : 0.0,
            child: Container(
              color: Colors.red,
            )
          ),
        ),
        Padding(
          padding: searchMargin,
          child: Align(
            alignment: Alignment.bottomCenter,
            child: title,
          ),
        )
      ],
    );
  }

  @override
  double get maxExtent => expandedHeight;

  @override
  double get minExtent => kToolbarHeight;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
} 

Upvotes: 4

Related Questions