1

如果 SliverAppbar 在 customScrollView 中,它将拉伸和缩放,但在 NestedScrollView 中则不会。只有 NestedScrollView 的 body 有 BouncingScrollPhysics,NestedScrollView 的 header 怎么也有 BouncingScrollPhysics 才能拉伸和缩放 SliverAppBar。

但是,如果我在 body/inner scrollView 中添加 scrollController 则标题 SliverAppBar 会拉伸,但随后它们会变成两个单独的滚动视图,并且当 body 滚动时标题不会向上滚动。检查 屏幕录制

      @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 3,
        child: NestedScrollView(
          physics: BouncingScrollPhysics(),
          controller: mainScroller,
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              SliverAppBar(
                stretch: true,
                pinned: true,
                floating: false,
                elevation: 0,
                onStretchTrigger: () {
                  print('stretch');
                  return;
                },
                title: isFlexibleSpaceVisible ? null : Text(widget.name),
                expandedHeight: containerHeight - kToolbarHeight,
                flexibleSpace: FlexibleSpaceBar(
                  stretchModes: <StretchMode>[
                    StretchMode.zoomBackground,
                    StretchMode.blurBackground,
                  ],
                  collapseMode: CollapseMode.pin,
                  background: Container(
                    color: Theme.of(context).canvasColor,
                    child: Stack(
                      children: <Widget>[
                        Container(
                          height: headerImageHeight,
                          width: double.infinity,
                          decoration: BoxDecoration(
                            color: kBackgroundColor,
                            image: DecorationImage(
                              fit: BoxFit.cover,
                              colorFilter: ColorFilter.mode(
                                Colors.black54,
                                BlendMode.darken,
                              ),
                              image: NetworkImage(
                                  'https://picsum.photos/seed/${Random().nextInt(100)}/${MediaQuery.of(context).size.width.toInt()}'),
                            ),
                          ),
                        ),
                        Container(
                          height: headerSpace,
                          margin: EdgeInsets.only(
                              top: headerImageHeight - bringImageUpMargin),
                          padding: EdgeInsets.only(left: 8, right: 8),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: <Widget>[
                              Container(
                                decoration: BoxDecoration(
                                    color: Theme.of(context).canvasColor,
                                    shape: BoxShape.circle),
                                padding: EdgeInsets.all(6),
                                child: CircleAvatar(
                                  backgroundColor: kCardColor,
                                  backgroundImage: NetworkImage(
                                      'https://picsum.photos/seed/${Random().nextInt(100)}/200'),
                                  radius: profileImageRadius,
                                ),
                              ),
                              Expanded(
                                child: Container(
                                  margin: EdgeInsets.symmetric(
                                      horizontal: 4, vertical: 12),
                                  child: Column(
                                    mainAxisAlignment: MainAxisAlignment.end,
                                    crossAxisAlignment:
                                        CrossAxisAlignment.stretch,
                                    children: <Widget>[
                                      Text(
                                        widget.name,
                                        style: TextStyle(
                                            fontSize: 16,
                                            fontWeight: FontWeight.w700),
                                      ),
                                      SizedBox(height: 2),
                                      Wrap(
                                        alignment: WrapAlignment.spaceBetween,
                                        children: <Widget>[
                                          Container(
                                            padding: EdgeInsets.symmetric(
                                                horizontal: 6, vertical: 2),
                                            decoration: BoxDecoration(
                                                color: kPrimaryColor,
                                                borderRadius:
                                                    BorderRadius.circular(4)),
                                            child: Text(
                                              widget.skill,
                                              style: TextStyle(
                                                  fontSize: 12,
                                                  color: Colors.white),
                                            ),
                                          ),
                                          Container(
                                            padding: EdgeInsets.symmetric(
                                                vertical: 2, horizontal: 6),
                                            decoration: BoxDecoration(
                                                color: kCardColor,
                                                borderRadius:
                                                    BorderRadius.circular(4)),
                                            child: Text(
                                              '\$${widget.rate} / ${widget.per}',
                                              style: TextStyle(
                                                  color: kPrimaryColor,
                                                  fontSize: 12),
                                            ),
                                          ),
                                        ],
                                      ),
                                    ],
                                  ),
                                ),
                              )
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
              SliverToBoxAdapter(
                child: Container(
                  padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                  child: Column(
                    children: <Widget>[
                      Row(
                        children: <Widget>[
                          Container(
                              width: 22,
                              height: 18,
                              decoration: BoxDecoration(
                                borderRadius: BorderRadius.circular(4),
                                color: kSecondaryColor,
                              ),
                              child: Icon(
                                Icons.star,
                                color: Colors.white,
                                size: 14,
                              )),
                          SizedBox(
                            width: 6,
                          ),
                          Text('Do you recommend ${widget.name} ?'),
                        ],
                      ),
                      Row(
                        children: <Widget>[
                          Expanded(
                            child: OutlineButton(
                              highlightedBorderColor: kSecondaryColor,
                              color: kSecondaryColor,
                              borderSide: BorderSide(color: kSecondaryColor),
                              textColor: kSecondaryColor,
                              onPressed: () => null,
                              child: Text('NO'),
                            ),
                          ),
                          SizedBox(
                            width: 8,
                          ),
                          Expanded(
                            child: RaisedButton(
                              onPressed: () => null,
                              child: Text('YES'),
                            ),
                          ),
                        ],
                      )
                    ],
                  ),
                ),
              ),
              SliverPersistentHeader(
                pinned: true,
                delegate: SliverProfileTabs(),
              )
            ];
          },
          body: ProfileTabsView(data: widget),
        ),
      ),
    );
  }
}
4

1 回答 1

4

正如评论中提到的,GitHub 中有一个开放的错误

此线程中讨论了此行为的原因:

没有发生拉伸的原因是因为 _NestedScrollViewCoodinator当前优先考虑用户拖动的任何过度滚动的内部可滚动。我在想我们可以添加一个像 , 的标志NestedScrollView.stretchHeaderSlivers,它将翻转它以将过度滚动发送到外部可滚动。那部分应该很容易。

_NestedScrollViewCoordinator.createOuterBallisticScrollActivity 需要重构,因为它目前假定外部可滚动永远不会过度滚动,这可能会也可能不会那么容易。

他们提到这是一个巨大的重构,还没有合适的解决方案:

我已经对此进行了几次尝试,但还没有找到合适的解决方案。NestedScrollView 的基础远比我假设外部滚动视图永远不会过度滚动。我相信这将需要对小部件进行更大的重构/重新设计以支持,也许我们可以在新的一年安排工作。现在,我不会再积极地做这件事了。我现在正在取消自己的分配,以防其他人同时想尝试解决这个问题。:)

由于我无法查看您的屏幕录像,因此我将仅发布该错误外观的示例视图。它取自GitHub 问题线程

示例代码:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      theme: ThemeData.dark(),
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
        length: 2,
        child: Scaffold(
          body: NestedScrollView(
              physics: BouncingScrollPhysics(),
              headerSliverBuilder: (context, innerScrolled) => <Widget>[
                    SliverOverlapAbsorber(
                      handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
                          context),
                      sliver: SliverAppBar(
                          pinned: true,
                          stretch: true,
                          title: Text('username'),
                          expandedHeight: 325,
                          flexibleSpace: FlexibleSpaceBar(
                              stretchModes: <StretchMode>[
                                StretchMode.zoomBackground,
                                StretchMode.blurBackground,
                              ],
                              background: Image.network(
                                  'https://i.imgur.com/QCNbOAo.png',
                                  fit: BoxFit.cover)),
                          bottom: TabBar(
                              tabs: <Widget>[Text('test1'), Text('test2')])),
                    )
                  ],
              body: TabBarView(children: [
                Center(
                  child: Builder(
                    builder: (context) => CustomScrollView(
                      slivers: <Widget>[
                        SliverOverlapInjector(
                            handle:
                                NestedScrollView.sliverOverlapAbsorberHandleFor(
                                    context)),
                        SliverFixedExtentList(
                            delegate: SliverChildBuilderDelegate(
                                (_, index) => Text('not working'),
                                childCount: 100),
                            itemExtent: 25)
                      ],
                    ),
                  ),
                ),
                Center(child: Text('working'))
              ])),
        ));
  }
}

输出:

在此处输入图像描述

于 2021-03-23T21:47:16.903 回答