flutter - 在 NestedScrollView 的外部滚动监听器
问题描述
我正在尝试创建材质原生选项卡,因此当我们滚动页面时,appbar 会折叠,但选项卡栏应该始终可见,我在 Flutter 中使用 NestedScrollView 实现了这一点
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
@override
void dispose() {
super.dispose();
_tabController.dispose();
}
@override
Widget build(BuildContext context) {
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool isBoxScrolled) {
return [
SliverAppBar(
title: Text("Scroller title"),
forceElevated: isBoxScrolled,
pinned: true,
floating: true,
bottom: TabBar(
tabs: [Tab(text: "tab1"), Tab(text: "tab2")],
controller: _tabController))
];
},
body: TabBarView(
children: [Page1(), Page1()],
controller: _tabController,
));
}
}
class Page1 extends StatefulWidget {
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
ScrollController _controller;
void _scrollListener(){
if(_controller.offset >= _controller.position.maxScrollExtent && !_controller.position.outOfRange){
print("reached the bottom");
}
}
@override
void initState() {
super.initState();
_controller = ScrollController();
_controller.addListener(_scrollListener);
}
@override
Widget build(BuildContext context) {
return ListView(
controller: _controller,
children: <Widget>[Text("data"), SizedBox(height: 2000.0)],
);
}
}
但是当我尝试在我的 tabBarview 小部件之一中使用 scrollController 时,它会断开与 appbar 的联系并单独滚动。
解决方案
解决方案是 PrimaryScrollController
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
@override
void dispose() {
super.dispose();
_tabController.dispose();
}
@override
Widget build(BuildContext context) {
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool isBoxScrolled) {
return [
SliverAppBar(
title: Text("Scroller title"),
forceElevated: isBoxScrolled,
pinned: true,
floating: true,
bottom: TabBar(
tabs: [Tab(text: "tab1"), Tab(text: "tab2")],
controller: _tabController))
];
},
body: Builder(
builder: (BuildContext context) {
final innerScrollController = PrimaryScrollController.of(context);
// Use the innerScrollController to listen to the scrolling.
// This would be your controller for list. You can listen to this controller to know whether the list has reached maxScrollExtent and fetch data from API.
return TabBarView(
children: [
Page1(innerScrollController),
Page1(innerScrollController)
],
controller: _tabController,
);
},
),
);
}
}
class Page1 extends StatefulWidget {
final ScrollController _PrimaryScrollController;
Page1(this._PrimaryScrollController);
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
void _scrollListener(){
if(this.widget._PrimaryScrollController.offset >= this.widget._PrimaryScrollController.position.maxScrollExtent && !this.widget._PrimaryScrollController.position.outOfRange){
print("reached the bottom");
}
}
@override
void initState() {
super.initState();
this.widget._PrimaryScrollController.addListener(_scrollListener);
}
@override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[Text("data"), SizedBox(height: 2000.0)],
);
}
}
推荐阅读
- c++ - 显示长数字 C++
- vscode-extensions - VSCode 扩展激活方法可以异步吗?
- php - $request->get() 时 laravel + 字符丢失
- sql - WHERE 子句中的 SQLite 计算列似乎正在工作(?)
- unity3d - Unity3D 零件运动
- python - Python如何将列表返回给其他函数?
- javascript - 如何使用节点 js 将字符串路径转换为 JSON 父子树?
- curl - 使用 mingw64 编译静态 cURL 时对 difftime64 的未定义引用
- arduino - ESP8266 WiFiUDP 发送数据包导致挂起然后崩溃
- angular - 通过表单控件从父级获取验证器