在 Flutter 中从 SingleChildScrollView 滚动 ListView inside PageView
Scroll ListView inside PageView from SingleChildScrollView in Flutter
我有一个标签栏,每个 TabBarView
里面都有一个 PageView
。每个 PageView
都有一个 ListView
,当我滚动它时,如何从脚手架的 SingleChildScrollView
滚动而不是只滚动 TabBarView
内的 ListView
?
目前,当我滚动 TabBarView
时,标签栏保持在相同的位置,这看起来很糟糕。如何从 SingleChildScrollView
滚动到 TabBarView
?
我尝试使用 physics
进行调整,但没有达到我想要的效果。
图像:
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
int currIndex = 0;
TabController _tabController;
@override
void initState() {
super.initState();
_tabController =
TabController(vsync: this, length: 3, initialIndex: currIndex);
_tabController.addListener(() {
_handleTabSelection();
});
}
void _handleTabSelection() {
setState(() {
currIndex = _tabController.index == null ? 0 : _tabController.index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: DefaultTabController(
length: 3,
initialIndex: 0,
child: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
Container(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8),
child: Container(
child: Text(
"HOME",
style: TextStyle(fontSize: 25),
)),
),
_buildTabBar(context),
],
),
),
Expanded(
child: _buildTabBarView(
context,
),
)
],
),
),
),
),
),
);
}
TabBarView _buildTabBarView(BuildContext context) {
return TabBarView(
controller: _tabController,
children: List.generate(
3,
(index) => Container(
color: Colors.red,
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 60,
color: Colors.blue,
child: Center(child: Text("$index"))),
);
},
),
)));
}
Widget _buildTabBar(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8),
child: Container(
height: 45,
width: double.infinity,
decoration: buildTabBarStyle(),
child: TabBar(
controller: _tabController,
isScrollable: false,
tabs: List.generate(
3,
(index) => Center(
child: Text(
"$index",
style: TextStyle(color: Colors.black),
),
)),
),
),
);
}
BoxDecoration buildTabBarStyle() {
return BoxDecoration(
color: Color.fromARGB(255, 230, 248, 255),
border: Border.all(
width: 1,
color: Colors.black,
),
borderRadius: BorderRadius.all(Radius.circular(10)),
);
}
}
这是一种简单的不同方法。
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
late final TabController controller;
@override
void initState() {
super.initState();
controller = TabController(length: 3, vsync: this);
}
BoxDecoration buildTabBarStyle() {
return BoxDecoration(
color: Color.fromARGB(255, 230, 248, 255),
border: Border.all(
width: 1,
color: Colors.black,
),
borderRadius: BorderRadius.all(Radius.circular(10)),
);
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
snap: true,
floating: true,
pinned: false,
toolbarHeight: 80,
title: Text("Home"),
// title: Search(),
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size(0.0, 48.0),
child: Container(
decoration: buildTabBarStyle(),
alignment: Alignment.center,
width: double.infinity,
child: TabBar(
controller: controller,
isScrollable: true,
labelColor: Colors.green,
unselectedLabelColor: Colors.grey,
labelStyle:
TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),
tabs: [
Tab(text: "1"),
Tab(text: "2"),
Tab(text: "3"),
],
),
),
),
),
],
body: TabBarView(
controller: controller,
children: [
...List.generate(
3,
(t) => Container(
color: Colors.red,
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 60,
color: Colors.blue,
child: Center(
child: Text("tab $t index $index"),
),
),
);
},
),
),
).toList(),
],
),
),
),
);
}
}
我有一个标签栏,每个 TabBarView
里面都有一个 PageView
。每个 PageView
都有一个 ListView
,当我滚动它时,如何从脚手架的 SingleChildScrollView
滚动而不是只滚动 TabBarView
内的 ListView
?
目前,当我滚动 TabBarView
时,标签栏保持在相同的位置,这看起来很糟糕。如何从 SingleChildScrollView
滚动到 TabBarView
?
我尝试使用 physics
进行调整,但没有达到我想要的效果。
图像:
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
int currIndex = 0;
TabController _tabController;
@override
void initState() {
super.initState();
_tabController =
TabController(vsync: this, length: 3, initialIndex: currIndex);
_tabController.addListener(() {
_handleTabSelection();
});
}
void _handleTabSelection() {
setState(() {
currIndex = _tabController.index == null ? 0 : _tabController.index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: DefaultTabController(
length: 3,
initialIndex: 0,
child: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
Container(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8),
child: Container(
child: Text(
"HOME",
style: TextStyle(fontSize: 25),
)),
),
_buildTabBar(context),
],
),
),
Expanded(
child: _buildTabBarView(
context,
),
)
],
),
),
),
),
),
);
}
TabBarView _buildTabBarView(BuildContext context) {
return TabBarView(
controller: _tabController,
children: List.generate(
3,
(index) => Container(
color: Colors.red,
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 60,
color: Colors.blue,
child: Center(child: Text("$index"))),
);
},
),
)));
}
Widget _buildTabBar(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8),
child: Container(
height: 45,
width: double.infinity,
decoration: buildTabBarStyle(),
child: TabBar(
controller: _tabController,
isScrollable: false,
tabs: List.generate(
3,
(index) => Center(
child: Text(
"$index",
style: TextStyle(color: Colors.black),
),
)),
),
),
);
}
BoxDecoration buildTabBarStyle() {
return BoxDecoration(
color: Color.fromARGB(255, 230, 248, 255),
border: Border.all(
width: 1,
color: Colors.black,
),
borderRadius: BorderRadius.all(Radius.circular(10)),
);
}
}
这是一种简单的不同方法。
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
late final TabController controller;
@override
void initState() {
super.initState();
controller = TabController(length: 3, vsync: this);
}
BoxDecoration buildTabBarStyle() {
return BoxDecoration(
color: Color.fromARGB(255, 230, 248, 255),
border: Border.all(
width: 1,
color: Colors.black,
),
borderRadius: BorderRadius.all(Radius.circular(10)),
);
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
snap: true,
floating: true,
pinned: false,
toolbarHeight: 80,
title: Text("Home"),
// title: Search(),
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size(0.0, 48.0),
child: Container(
decoration: buildTabBarStyle(),
alignment: Alignment.center,
width: double.infinity,
child: TabBar(
controller: controller,
isScrollable: true,
labelColor: Colors.green,
unselectedLabelColor: Colors.grey,
labelStyle:
TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),
tabs: [
Tab(text: "1"),
Tab(text: "2"),
Tab(text: "3"),
],
),
),
),
),
],
body: TabBarView(
controller: controller,
children: [
...List.generate(
3,
(t) => Container(
color: Colors.red,
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 60,
color: Colors.blue,
child: Center(
child: Text("tab $t index $index"),
),
),
);
},
),
),
).toList(),
],
),
),
),
);
}
}