如何使`NestedScrollView`仅在必要时滚动其内容。

huangapple go评论67阅读模式
英文:

How to make `NestedScrollView` only scroll its body when necessary

问题

我正在使用 NestedScrollView.headerSliverBuilder 属性来复制 iOS 中滚动屏幕内容时折叠页面标题的行为,就像下面的 GIF 所示:

如何使`NestedScrollView`仅在必要时滚动其内容。

到目前为止,它运行得非常好。问题是,当屏幕内容低于屏幕边界时,我想阻止 NestedScrollView 的主体滚动,因为理论上不需要滚动,因为所有内容都可见(就像 GIF 示例中一样)。

这是我在 GIF 示例中使用的代码:

@override
Widget build(BuildContext context) {
  return CupertinoPageScaffold(
    child: NestedScrollView(
      headerSliverBuilder: (context, innerBoxIsScrolled) => [
        SliverOverlapAbsorber(
          handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
          sliver: SliverSafeArea(
            top: false,
            bottom: false,
            sliver: CupertinoSliverNavigationBar(largeTitle: Text('Page Title')),
          ),
        ),
      ],
      body: Material(
        child: SafeArea(
          top: false,
          child: Center(child: Container(color: Colors.red, height: 50)),
        ),
      ),
    ),
  );
}
英文:

I'm using NestedScrollView.headerSliverBuilder property to reproduce the same iOS behavior of collapsing the page title when scrolling the screen content, like the GIF below illustrate

如何使`NestedScrollView`仅在必要时滚动其内容。

And it's working really good so far. The problem is that, when the screen content is lower than the screen bounds, I would like to block the NestedScrollView body scroll, since in theory it wouldn't be necessary to scroll because all the content is visible (just like the GIF example).

Here's the code I'm using in the GIF example:

@override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: NestedScrollView(
        headerSliverBuilder: (context, innerBoxIsScrolled) => [
          SliverOverlapAbsorber(
            handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
            sliver: SliverSafeArea(
              top: false,
              bottom: false,
              sliver: CupertinoSliverNavigationBar(largeTitle: Text('Page Title')),
            ),
          ),
        ],
        body: Material(
          child: SafeArea(
            top: false,
            child: Center(child: Container(color: Colors.red, height: 50)),
          ),
        ),
      ),
    );
  }

答案1

得分: 2

请使用CustomScrollView而不是NestedScrollView

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: CustomScrollView(
        slivers: [
          const SliverSafeArea(
            top: false,
            bottom: false,
            sliver: CupertinoSliverNavigationBar(largeTitle: Text('页面标题')),
          ),
          SliverToBoxAdapter(
            child: Material(
              child: SafeArea(
                top: false,
                child: Center(child: Container(color: Colors.red, height: 50)),
              ),
            ),
          ),
        ],
      ),
    );
  }
英文:

Use CustomScrollView instead of NestedScrollView:

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: CustomScrollView(
        slivers: [
          const SliverSafeArea(
            top: false,
            bottom: false,
            sliver:
                CupertinoSliverNavigationBar(largeTitle: Text('Page Title')),
          ),
          SliverToBoxAdapter(
            child: Material(
              child: SafeArea(
                top: false,
                child: Center(child: Container(color: Colors.red, height: 50)),
              ),
            ),
          ),
        ],
      ),
    );
  }

答案2

得分: 1

我建议保持内置的行为不变。要复制具有更好动画、流畅性和集成ClampingScroll的减小应用栏,您可以使用CustomScrollViewSliverAppBar

随意更改itemCount以查看滚动时的行为,还可以更改FlexibleSpaceBar以复制您想要的AppBar。您可以添加背景图片等。

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            floating: true,
            snap: true,
            expandedHeight: 200.0,
            flexibleSpace: FlexibleSpaceBar(
              title: Text("Twitter-like AppBar"),
            ),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              childCount: 3,
              (context, index) => ListTile(
                title: Text('Item #${index}'),
              ),
            ),
          ),
        ],
      ),
    );
  }
英文:

I would recommend to stick with the builtin behaviors
To reproduce this kind of reducing app bar with better animation, fluidity and integrated ClampingScroll you could use a CustomScrollView with a SliverAppBar.

Feel free to change the itemCount to see the behavior when its scrolling, also change the FlexibleSpaceBar to reproduce the AppBar you want. You can add background image and more.

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: &lt;Widget&gt;[
          SliverAppBar(
            pinned: true,
            floating: true,
            snap: true,
            expandedHeight: 200.0,
            flexibleSpace: FlexibleSpaceBar(
              title: Text(&quot;Twitter-like AppBar&quot;),
            ),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              childCount: 3,
              (context, index) =&gt; ListTile(
                title: Text(&#39;Item #${index}&#39;),
              ),
            ),
          ),
        ],
      ),
    );
  }

huangapple
  • 本文由 发表于 2023年6月16日 10:32:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486620.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定