Flutter嵌套滚动视图插件extended_nested_scroll_view的使用
Flutter嵌套滚动视图插件extended_nested_scroll_view的使用
extended_nested_scroll_view
NestedScrollView
是Flutter中用于实现复杂滚动效果的重要组件。但是它存在一些问题,如固定标题栏的高度问题、TabView内部可滚动组件同步问题等。extended_nested_scroll_view
插件扩展了 NestedScrollView
,解决了这些问题,并且提供了更多的功能。
主要解决的问题
- pinned sliver header issue:修复了固定标题栏高度的问题。
- inner scrollables in tabview sync issue:修复了TabView内部可滚动组件同步的问题。
- do without ScrollController in NestedScrollView’s body:在
NestedScrollView
的主体部分不使用ScrollController
。
Web demo for ExtendedNestedScrollView
示例代码
Example for issue 1
给定固定标题栏的总高度,在 pinnedHeaderSliverHeightBuilder
回调中返回该高度。
var tabBarHeight = primaryTabBar.preferredSize.height;
var pinnedHeaderHeight =
// 状态栏高度
statusBarHeight +
// 固定 SliverAppBar 高度
kToolbarHeight;
ExtendedNestedScrollView(
pinnedHeaderSliverHeightBuilder: () {
return pinnedHeaderHeight;
},
);
Example for issue 2
我们通常通过以下方式保持列表的滚动位置:
scene | onlyOneScrollInBody | description |
---|---|---|
AutomaticKeepAliveClientMixin | true | 滚动位置不会被销毁,设置 onlyOneScrollInBody 为 true,以便我们知道哪个列表是激活的。 |
PageStorageKey | false | 滚动位置会被销毁,PageStorageKey 只记录位置信息,ExtendedNestedScrollView 中的滚动位置始终是单一的。 |
ExtendedNestedScrollView(
onlyOneScrollInBody: true,
)
ExtendedVisibilityDetector
提供 ExtendedVisibilityDetector
来指出哪个列表是可见的。
ExtendedVisibilityDetector(
uniqueKey: const Key('Tab1'),
child: ListView(),
)
Do without ScrollController in NestedScrollView’s body
由于我们不能为 NestedScrollView
的主体部分设置 ScrollController
(这会破坏 InnerScrollController
在 NestedScrollView
中的行为),因此提供了以下示例来展示如何在不使用 ScrollController
的情况下实现某些功能:
完整示例Demo
下面是一个完整的示例代码,展示了如何使用 extended_nested_scroll_view
插件:
import 'package:flutter/material.dart';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'extended_nested_scroll_view demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
final List<String> _tabs = ['Tab 1', 'Tab 2'];
TabController? _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: _tabs.length, vsync: this);
}
@override
void dispose() {
_tabController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('extended_nested_scroll_view Demo'),
bottom: TabBar(
controller: _tabController,
tabs: _tabs.map((String name) => Tab(text: name)).toList(),
),
),
body: ExtendedNestedScrollView(
pinnedHeaderSliverHeightBuilder: () {
return kToolbarHeight + MediaQuery.of(context).padding.top;
},
onlyOneScrollInBody: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverOverlapAbsorber(
handle: ExtendedNestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: SliverAppBar(
title: Text('Pinned Header'),
floating: false,
pinned: true,
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
'https://via.placeholder.com/350x150',
fit: BoxFit.cover,
),
),
),
),
];
},
body: TabBarView(
controller: _tabController,
children: _tabs.map((String name) {
return Builder(
builder: (BuildContext context) {
return ExtendedVisibilityDetector(
uniqueKey: Key(name),
child: ListView.builder(
itemCount: 50,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('$name Item $index'));
},
),
);
},
);
}).toList(),
),
),
);
}
}
这个示例展示了如何使用 extended_nested_scroll_view
插件创建一个带有固定标题栏和多个标签页的嵌套滚动视图。每个标签页包含一个可滚动的列表,并且可以通过 ExtendedVisibilityDetector
来检测当前可见的列表。
更多关于Flutter嵌套滚动视图插件extended_nested_scroll_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter嵌套滚动视图插件extended_nested_scroll_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用 extended_nested_scroll_view
插件在 Flutter 中实现嵌套滚动视图的代码示例。这个插件允许你在一个滚动视图中嵌套另一个滚动视图,这在实现复杂的 UI 布局时非常有用。
首先,确保你已经在 pubspec.yaml
文件中添加了 extended_nested_scroll_view
依赖:
dependencies:
flutter:
sdk: flutter
extended_nested_scroll_view: ^x.y.z # 请替换为最新版本号
然后,运行 flutter pub get
来获取依赖。
接下来是一个完整的 Flutter 应用示例,展示了如何使用 ExtendedNestedScrollView
:
import 'package:flutter/material.dart';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: NestedScrollViewDemo(),
);
}
}
class NestedScrollViewDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Extended Nested Scroll View Demo'),
),
body: ExtendedNestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text('Header'),
pinned: true,
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
'https://via.placeholder.com/800x200',
fit: BoxFit.cover,
),
),
),
];
},
body: Column(
children: <Widget>[
// 第一个滚动区域
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(
20,
(index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 100,
height: 100,
color: Colors.primary.withOpacity(0.5),
child: Center(child: Text('Item $index')),
),
),
),
),
),
// 第二个滚动区域(垂直滚动)
Expanded(
child: SingleChildScrollView(
child: Column(
children: List.generate(
50,
(index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 50,
color: Colors.accent.withOpacity(0.5),
child: Center(child: Text('Item $index')),
),
),
),
),
),
),
],
),
),
);
}
}
解释
ExtendedNestedScrollView
:这是插件提供的主要组件,它允许嵌套滚动视图。headerSliverBuilder
:这是一个回调函数,用于构建头部(通常是一个SliverAppBar
)。SingleChildScrollView
:用于在水平或垂直方向上创建滚动区域。SliverAppBar
:一个可以固定在顶部的AppBar
,并可以在滚动时扩展或收缩。
在这个示例中,我们创建了一个包含头部(带有图片的背景)的嵌套滚动视图,头部下面是两个滚动区域:
- 第一个区域是水平滚动的,包含 20 个水平排列的项。
- 第二个区域是垂直滚动的,包含 50 个垂直排列的项。
这个示例展示了如何使用 extended_nested_scroll_view
插件在 Flutter 中实现复杂的嵌套滚动视图布局。你可以根据需要调整这个示例来适应你的应用。