管理 SingleChildScrollView 内 SingleChildScrollView 的滚动 - 抖动?
Manage scrolling for SingleChildScrollView inside a SingleChildScrollView - flutter?
我有一个父 SCS 视图 (SingleChildScrollView) 和一个子 SCS 视图。在子 SCS 视图中有一个数据 Table,数据 Table 从屏幕底部四分之一左右开始。
现在,当用户滚动到子 SCS 视图中数据 Table 的顶部时,我想滚动父 SCS 视图。
这在 web 中自然有效,但在 iOS 或 anroid 中无效。我尝试对父 SCS 视图和子 SCS 视图使用相同的 Scrollcontroller,并尝试使用 ScrollPhysics。但似乎没有任何效果。你能帮我解决一下吗?
代码如下:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Report'),
),
),
),
);
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final ScrollController scrollController = ScrollController();
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 400,
),
child: Scrollbar(
controller: scrollController,
child: SingleChildScrollView(
controller: scrollController,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: [
DataColumn(label: Text('Sl. No.')),
DataColumn(label: Text('Resource Name')),
DataColumn(label: Text('Score at 1')),
DataColumn(label: Text('Score at 2')),
DataColumn(label: Text('Final Score')),
],
rows: [
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
],
),
),
),
),
)
],
),
);
}
}
谢谢。
已编辑
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:so_test/screen/video_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
UniqueKey _key = UniqueKey();
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Test(),
);
}
}
class Test extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _TestState();
}
}
class _TestState extends State<Test> {
final ScrollController scrollController = ScrollController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
children: [
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Scrollbar(
controller: scrollController,
child: SingleChildScrollView(
controller: scrollController,
physics: NeverScrollableScrollPhysics(),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: [
DataColumn(label: Text('Sl. No.')),
DataColumn(label: Text('Resource Name')),
DataColumn(label: Text('Score at 1')),
DataColumn(label: Text('Score at 2')),
DataColumn(label: Text('Final Score')),
],
rows: [
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
],
),
),
),
)
],
),
),
);
}
}
可以使用NotificationListener监听OverscrollNotification
检测嵌套列表的上边界命中,通过控制滚动到外层Scrollview
我将您的问题简化为以下示例代码:
class MyNestedListView extends StatefulWidget {
const MyNestedListView({Key? key}) : super(key: key);
@override
_MyNestedListViewState createState() => _MyNestedListViewState();
}
class _MyNestedListViewState extends State<MyNestedListView> {
final _controller = ScrollController();
@override
Widget build(BuildContext context) {
return ListView(
controller: _controller,
children: [
Placeholder(fallbackHeight: 400),
Placeholder(fallbackHeight: 400),
Placeholder(fallbackHeight: 400),
Container(
padding: EdgeInsets.symmetric(horizontal: 20),
height: 400,
child: NotificationListener(
onNotification: (notification) {
// disable overscroll indicator
// if (notification is OverscrollIndicatorNotification) {
// if (notification.leading) {
// notification.disallowGlow();
// }
// }
if (notification is OverscrollNotification) {
final dy = notification.overscroll;
if (dy < 0) {
_controller.position.jumpTo(_controller.offset + dy);
}
}
return true;
},
child: ListView(
children: [
Placeholder(fallbackHeight: 200),
Placeholder(fallbackHeight: 200),
Placeholder(fallbackHeight: 200),
Placeholder(fallbackHeight: 200),
],
),
),
)
],
);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
}
我有一个父 SCS 视图 (SingleChildScrollView) 和一个子 SCS 视图。在子 SCS 视图中有一个数据 Table,数据 Table 从屏幕底部四分之一左右开始。
现在,当用户滚动到子 SCS 视图中数据 Table 的顶部时,我想滚动父 SCS 视图。
这在 web 中自然有效,但在 iOS 或 anroid 中无效。我尝试对父 SCS 视图和子 SCS 视图使用相同的 Scrollcontroller,并尝试使用 ScrollPhysics。但似乎没有任何效果。你能帮我解决一下吗?
代码如下:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Report'),
),
),
),
);
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final ScrollController scrollController = ScrollController();
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 400,
),
child: Scrollbar(
controller: scrollController,
child: SingleChildScrollView(
controller: scrollController,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: [
DataColumn(label: Text('Sl. No.')),
DataColumn(label: Text('Resource Name')),
DataColumn(label: Text('Score at 1')),
DataColumn(label: Text('Score at 2')),
DataColumn(label: Text('Final Score')),
],
rows: [
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
],
),
),
),
),
)
],
),
);
}
}
谢谢。
已编辑
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:so_test/screen/video_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
UniqueKey _key = UniqueKey();
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Test(),
);
}
}
class Test extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _TestState();
}
}
class _TestState extends State<Test> {
final ScrollController scrollController = ScrollController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
children: [
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Text('Some Data', style: TextStyle(fontSize: 30)),
Scrollbar(
controller: scrollController,
child: SingleChildScrollView(
controller: scrollController,
physics: NeverScrollableScrollPhysics(),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: [
DataColumn(label: Text('Sl. No.')),
DataColumn(label: Text('Resource Name')),
DataColumn(label: Text('Score at 1')),
DataColumn(label: Text('Score at 2')),
DataColumn(label: Text('Final Score')),
],
rows: [
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
DataRow(
cells: [
DataCell(Text('1')),
DataCell(Text('Person 1')),
DataCell(Text('5')),
DataCell(Text('2')),
DataCell(Text('8')),
],
),
],
),
),
),
)
],
),
),
);
}
}
可以使用NotificationListener监听OverscrollNotification
检测嵌套列表的上边界命中,通过控制滚动到外层Scrollview
我将您的问题简化为以下示例代码:
class MyNestedListView extends StatefulWidget {
const MyNestedListView({Key? key}) : super(key: key);
@override
_MyNestedListViewState createState() => _MyNestedListViewState();
}
class _MyNestedListViewState extends State<MyNestedListView> {
final _controller = ScrollController();
@override
Widget build(BuildContext context) {
return ListView(
controller: _controller,
children: [
Placeholder(fallbackHeight: 400),
Placeholder(fallbackHeight: 400),
Placeholder(fallbackHeight: 400),
Container(
padding: EdgeInsets.symmetric(horizontal: 20),
height: 400,
child: NotificationListener(
onNotification: (notification) {
// disable overscroll indicator
// if (notification is OverscrollIndicatorNotification) {
// if (notification.leading) {
// notification.disallowGlow();
// }
// }
if (notification is OverscrollNotification) {
final dy = notification.overscroll;
if (dy < 0) {
_controller.position.jumpTo(_controller.offset + dy);
}
}
return true;
},
child: ListView(
children: [
Placeholder(fallbackHeight: 200),
Placeholder(fallbackHeight: 200),
Placeholder(fallbackHeight: 200),
Placeholder(fallbackHeight: 200),
],
),
),
)
],
);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
}