英文:
How to make `NestedScrollView` only scroll its body when necessary
问题
我正在使用 NestedScrollView.headerSliverBuilder
属性来复制 iOS 中滚动屏幕内容时折叠页面标题的行为,就像下面的 GIF 所示:
到目前为止,它运行得非常好。问题是,当屏幕内容低于屏幕边界时,我想阻止 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
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的减小应用栏,您可以使用CustomScrollView
和SliverAppBar
。
随意更改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: <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}'),
),
),
),
],
),
);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论