Flutter 在颤振中滚动类似yelp应用程序的动画

Flutter 在颤振中滚动类似yelp应用程序的动画,flutter,flutter-layout,Flutter,Flutter Layout,我正在尝试创建一个类似以下内容的CustomScrollView: 我用的是滑动条,但似乎不是正确的方法。到目前为止,我的代码是: CustomScrollView( slivers: <Widget>[ SliverAppBar( expandedHeight: 340, pinned: true, flexibleSpace: FlexibleSpaceBar(

我正在尝试创建一个类似以下内容的CustomScrollView:

我用的是滑动条,但似乎不是正确的方法。到目前为止,我的代码是:

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(...) 
CustomScrollView(
条子:[
滑杆(
扩展高度:340,
对,,
flexibleSpace:FlexibleSpaceBar(
背景:BackgroundImageWidget(),
标题:对,
//标题:文本(“在Kreis Kleve中按城市或活动搜索”),
标题:SearchButtonWidget(),
),
),
),
SliverList(…)
我得到的是:

我不明白为什么SearchButtonWidget一开始这么大。当它缩小时,它的大小是合适的。 带fliexibleSpace的sliverAppBar是正确的方法吗

编辑:有人能告诉我如何使搜索按钮与下面的小部件重叠吗?我想SliveAppBar做不到

编辑2:可能是图像下添加了白色背景。我需要对此进行调查。

@override
@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))
          ],
        ),
      ),
    );
  } 
小部件构建(构建上下文){ 返回脚手架( 正文:安全区( 托普:没错, 子:自定义滚动视图( 条子:[ 滑冰机( 代表:mysliveappbar( 扩展高度:250, 标题:集装箱( 边缘:边缘组。对称(水平:20.0,垂直:0), 装饰:盒子装饰( 颜色:颜色。灰色[200], borderRadius:borderRadius.all(半径.圆形(5.0)), 子对象:行(子对象:[ 填充物( 填充:仅限边缘设置(左:20.0,右:10.0), 子:图标(Icons.search), ), 扩大( 子项:TextFormField( 键盘类型:TextInputType.text, textInputAction:textInputAction.done, 光标颜色:颜色。黑色, 自动对焦:错误, 装饰:输入装饰( 是的, fillColor:Colors.transparent, contentPadding:EdgeInsets.symmetric( 垂直:10,水平:15), hintText:“搜索”, 边框:InputBorder.none, disabledBorder:OutlineInputBorder( 边界: 新边框(颜色:颜色。透明), 边界半径:新边界半径。圆形(2), ), 聚焦顺序:大纲输入边框( 边界: 新边框(颜色:颜色。透明), 边界半径:新边界半径。圆形(2), )), ), ) ]), )), 对,, ), 银表( 委托:SliverChildBuilderDelegate((上下文,索引){ 返回容器( 孩子:ListTile( 标题:文本(“${index}a”), )); },儿童人数:25) ], ), ), ); }

类MySliverAppBar扩展SliverPersistentHeaderDelegate{
最终双膨胀高度;
最终小部件标题;
mySliveAppBar({@required this.expandedHeight,this.title});
最终_avatarMarginTween=边缘之间(
开始:仅限边集(底部:20),
结束:仅限边缘设置(
底部:0.0,
));
最终搜索边缘之间=边缘之间(
开始:仅限边集(底部:0),
结束:仅限边缘组(底部:8,);
决赛=
对齐之间(开始:对齐.bottomCenter,结束:对齐.center);
@凌驾
小部件构建(
BuildContext上下文、双收缩偏移、布尔重叠内容){
双温度=75*maxExtent/100;
最终进度=shrinkOffset>tempVal?1.0:shrinkOffset/tempVal;
final avatarMargin=\u avatarMarginTween.lerp(progress);
最终搜索边际=_searchMarginTween.lerp(进度);
最终搜索对齐=进度>0.8?\u avatarAlignTween.lerp(进度):\u avatarAlignTween.lerp(0);
返回堆栈(
fit:StackFit.expand,
溢出:溢出。可见,
儿童:[
填充物(
填充:阿凡达精,
孩子:Image.network(
"https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
适合:BoxFit.cover,
),
),
居中(
子对象:不透明度(
不透明度:收缩偏移/展开高度>0.7?收缩偏移/展开高度:0.0,
子:容器(
颜色:颜色,红色,
)
),
),
填充物(
填充:搜索边距,
子对象:对齐(
对齐:对齐.bottomCenter,
孩子:头衔,
),
)
],
);
}
@凌驾
double get maxExtent=>expandedHeight;
@凌驾
double get minExtent=>kToolbarHeight;
@凌驾
布尔应该重建(SliverPersistentHeaderDelegate oldDelegate)=>true;
} 
@覆盖
小部件构建(构建上下文){
返回脚手架(
正文:安全区(
托普:没错,
子:自定义滚动视图(
条子:[
滑冰机(
代表:mysliveappbar(
扩展高度:250,
标题:集装箱(
玛格
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;
}