我有以下代码来演示我遇到的问题。我有一个嵌套的
ListView
,我希望当用户到达子项的末尾或开始时,子项的滚动“投降”到父项的滚动。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scroll example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: ListView(
children: [
for (int i = 0; i < 10; i++) ListItem(),
SizedBox(
height: 120,
child: ListView(
shrinkWrap: true,
children: [
for (int i = 0; i < 10; i++) ListItem2(),
],
),
),
for (int i = 0; i < 10; i++) ListItem(),
],
),
));
}
}
class ListItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListTile(
title: Text('Item'),
tileColor: Colors.blue,
);
}
}
class ListItem2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListTile(
title: Text('Item',
style: TextStyle(
color: Colors.red,
)),
);
}
}
我还录制了该问题的演示:https://www.youtube.com/watch?v=fmaR9rYMGd4
另外,这里有一个它按照我期望的方式在 Web 上的 Flutter 中工作的示例:
https://www.youtube.com/watch?v=cLxyPpb94M4
输出
flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.4, on macOS 13.5 22G74 darwin-arm64, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.0.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.3)
[✓] VS Code (version 1.88.1)
[✓] Connected device (3 available)
[✓] Network resources
• No issues found!
您只需要使用 ScrollController,NotificationListener 并使用一些 scrollExtents 和 offsets。
查看下面的代码。它会完成这项工作。希望这对您的用例有所帮助。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
ScrollController controller = ScrollController();
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scroll example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: ListView(
controller: controller,
children: [
for (int i = 0; i < 10; i++) ListItem(),
Container(
height: 120,
child: NotificationListener<OverscrollNotification>(
onNotification: (OverscrollNotification value) {
if (value.overscroll < 0 &&
controller.offset + value.overscroll <= 0) {
if (controller.offset != 0) controller.jumpTo(0);
return true;
}
if (controller.offset + value.overscroll >=
controller.position.maxScrollExtent) {
if (controller.offset !=
controller.position.maxScrollExtent) {
controller.jumpTo(controller.position.maxScrollExtent);
}
return true;
}
controller.jumpTo(controller.offset + value.overscroll);
return true;
},
child: ListView.builder(
itemBuilder: (c, ii) => ListItem2(),
itemCount: 20,
),
),
),
for (int i = 0; i < 10; i++) ListItem(),
],
),
),
);
}
}
class ListItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListTile(
title: Text('Item'),
tileColor: Colors.blue,
);
}
}
class ListItem2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListTile(
title: Text('Item',
style: TextStyle(
color: Colors.red,
)),
);
}
}