水平滚动视图中的 Flutter 滚动条无法正确显示内部滚动视图
Flutter scrollbar that is in horizontal scrollview doesnt show correctly inner scrollview
因此,我有较大的水平滚动滚动视图,以及内部 - 小框(红色)和较小的垂直滚动滚动视图(橙色)。
较大的滚动视图上有两个滚动条(1 - 用于水平),第二个 - 用于垂直内部。
还有问题 - 垂直滚动条看起来不对,因为它只能像蓝色箭头所示那样移动,我希望它具有较大滚动视图的全高,或者就在可滚动的垂直部分附近,但是不如果在水平方向滚动,则隐藏自身。
运行 在 dartPad 上
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: ScrollSizingWidget(),
),
),
);
}
}
class ScrollSizingWidget extends StatefulWidget {
const ScrollSizingWidget({
Key? key,
}) : super(key: key);
@override
State<ScrollSizingWidget> createState() => _ScrollSizingWidgetState();
}
class _ScrollSizingWidgetState extends State<ScrollSizingWidget> {
final ScrollController _horizontal = ScrollController();
final ScrollController _vertical = ScrollController();
@override
void dispose() {
_horizontal.dispose();
_vertical.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scrollbar(
controller: _vertical,
notificationPredicate: (notification) => notification.depth == 1,
child: Scrollbar(
controller: _horizontal,
scrollbarOrientation: ScrollbarOrientation.bottom,
child: SingleChildScrollView(
controller: _horizontal,
scrollDirection: Axis.horizontal,
child: SizedBox(
height: 500,
width: 1000,
child: Column(
children:[
Container(width: 1000, height: 200, color: Colors.green),
Flexible(
child: SingleChildScrollView(
controller: _vertical,
child: Container(
height: 700,
width: 1000,
color: Colors.yellow,
)
)
),
]
)
),
),
),
);
}
}
我已经使用你的代码重现了这个问题。如果我理解你的需求是正确的,这里是解决方法:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: const Scaffold(
body: Center(
child: SafeArea(
child: ScrollSizingWidget(),
),
),
),
);
}
class ScrollSizingWidget extends StatefulWidget {
const ScrollSizingWidget({Key? key}) : super(key: key);
@override
State<ScrollSizingWidget> createState() => _ScrollSizingWidgetState();
}
class _ScrollSizingWidgetState extends State<ScrollSizingWidget> {
late final ScrollController _horizontal;
late final ScrollController _vertical;
@override
void initState() {
super.initState();
_horizontal = ScrollController();
_vertical = ScrollController();
}
@override
void dispose() {
_horizontal.dispose();
_vertical.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Scrollbar(
controller: _horizontal,
scrollbarOrientation: ScrollbarOrientation.bottom,
child: SingleChildScrollView(
controller: _horizontal,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.zero,
child: SizedBox(
height: 500,
width: 1000,
child: Scrollbar(
controller: _vertical,
scrollbarOrientation: ScrollbarOrientation.right,
child: SingleChildScrollView(
controller: _vertical,
scrollDirection: Axis.vertical,
child: Column(
children: [
Container(
height: 200,
width: 1000,
color: Colors.red,
),
Container(
height: 1000,
width: 1000,
color: Colors.orange,
),
],
),
),
),
),
),
);
}
首先,您说您的主要 SingleChildScrollView
水平滚动,但您的小部件树以 Scrollbar
开始,它使用垂直 ScrollController
。所以你应该像你解释的那样一步一步地创建你的小部件。
另外,因为你想通过主 SingleChildScrollView
看到垂直 Scrollbar
,我用 Scrollbar
和 SingleChildScrollView
包装了两个(红色和橙色容器)到有你想要的效果。此外,我将这些 Scrollbar
和 SingleChildScrollView
连接到相同的水平 ScrollController
。所以现在,不仅是橙色 Container
,而且两者都可以滚动并粘在一起,而不是独立的。
如果您不希望红色 Container
与橙色 Container
一起滚动,请检查:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: const Scaffold(
body: Center(
child: SafeArea(
child: ScrollSizingWidget(),
),
),
),
);
}
class ScrollSizingWidget extends StatefulWidget {
const ScrollSizingWidget({Key? key}) : super(key: key);
@override
State<ScrollSizingWidget> createState() => _ScrollSizingWidgetState();
}
class _ScrollSizingWidgetState extends State<ScrollSizingWidget> {
late final ScrollController _horizontal;
late final ScrollController _vertical;
@override
void initState() {
super.initState();
_horizontal = ScrollController();
_vertical = ScrollController();
}
@override
void dispose() {
_horizontal.dispose();
_vertical.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Scrollbar(
controller: _horizontal,
scrollbarOrientation: ScrollbarOrientation.bottom,
child: SingleChildScrollView(
controller: _horizontal,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.zero,
child: SizedBox(
height: 500,
width: 1000,
child: Column(
children: [
Container(
height: 200,
width: 1000,
color: Colors.red,
),
Expanded(
child: Scrollbar(
controller: _vertical,
scrollbarOrientation: ScrollbarOrientation.right,
child: SingleChildScrollView(
controller: _vertical,
scrollDirection: Axis.vertical,
child: Container(
height: 700,
width: 1000,
color: Colors.orange,
),
),
),
),
],
),
),
),
);
}
最后,Scrollbar
在 iOS 中的位置由于缺口等原因有点错误。所以我用 SafeArea
包裹了你的 ScrollSizingWidget
来修复iOS.
中的问题
如果这些答案不是您所期望的,请不要犹豫写信。
编辑:在您在下面的评论中进行解释后,我创建了另一个修复程序。我相信 CustomScrollView
和 Sliver
小部件非常适合这里。红色 Container
,你想留在它的位置,应该用 SliverAppBar
包裹起来。最后,您希望能够垂直滚动的橙色 Container
可以用 SliverFixedExtentList
包裹起来。请检查以下代码:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: const Scaffold(
body: Center(
child: SafeArea(
child: ScrollSizingWidget(),
),
),
),
);
}
class ScrollSizingWidget extends StatefulWidget {
const ScrollSizingWidget({Key? key}) : super(key: key);
@override
State<ScrollSizingWidget> createState() => _ScrollSizingWidgetState();
}
class _ScrollSizingWidgetState extends State<ScrollSizingWidget> {
late final ScrollController _horizontal;
late final ScrollController _vertical;
@override
void initState() {
super.initState();
_horizontal = ScrollController();
_vertical = ScrollController();
}
@override
void dispose() {
_horizontal.dispose();
_vertical.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Scrollbar(
controller: _horizontal,
scrollbarOrientation: ScrollbarOrientation.bottom,
child: SingleChildScrollView(
controller: _horizontal,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.zero,
child: SizedBox(
height: 500,
width: 1000,
child: Scrollbar(
controller: _vertical,
scrollbarOrientation: ScrollbarOrientation.right,
child: CustomScrollView(
controller: _vertical,
scrollDirection: Axis.vertical,
slivers: [
SliverAppBar(
toolbarHeight: 200.0,
collapsedHeight: 200.0,
pinned: true,
stretch: true,
elevation: 0.0,
backgroundColor: Colors.transparent,
title: Container(
height: 200.0,
color: Colors.red,
),
titleSpacing: 0,
),
SliverFixedExtentList(
itemExtent: 1200.0,
delegate: SliverChildBuilderDelegate(
(_, __) => Container(
color: Colors.orange,
),
childCount: 1,
),
),
],
),
),
),
),
);
}
因此,我有较大的水平滚动滚动视图,以及内部 - 小框(红色)和较小的垂直滚动滚动视图(橙色)。 较大的滚动视图上有两个滚动条(1 - 用于水平),第二个 - 用于垂直内部。
还有问题 - 垂直滚动条看起来不对,因为它只能像蓝色箭头所示那样移动,我希望它具有较大滚动视图的全高,或者就在可滚动的垂直部分附近,但是不如果在水平方向滚动,则隐藏自身。
运行 在 dartPad 上
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: ScrollSizingWidget(),
),
),
);
}
}
class ScrollSizingWidget extends StatefulWidget {
const ScrollSizingWidget({
Key? key,
}) : super(key: key);
@override
State<ScrollSizingWidget> createState() => _ScrollSizingWidgetState();
}
class _ScrollSizingWidgetState extends State<ScrollSizingWidget> {
final ScrollController _horizontal = ScrollController();
final ScrollController _vertical = ScrollController();
@override
void dispose() {
_horizontal.dispose();
_vertical.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scrollbar(
controller: _vertical,
notificationPredicate: (notification) => notification.depth == 1,
child: Scrollbar(
controller: _horizontal,
scrollbarOrientation: ScrollbarOrientation.bottom,
child: SingleChildScrollView(
controller: _horizontal,
scrollDirection: Axis.horizontal,
child: SizedBox(
height: 500,
width: 1000,
child: Column(
children:[
Container(width: 1000, height: 200, color: Colors.green),
Flexible(
child: SingleChildScrollView(
controller: _vertical,
child: Container(
height: 700,
width: 1000,
color: Colors.yellow,
)
)
),
]
)
),
),
),
);
}
}
我已经使用你的代码重现了这个问题。如果我理解你的需求是正确的,这里是解决方法:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: const Scaffold(
body: Center(
child: SafeArea(
child: ScrollSizingWidget(),
),
),
),
);
}
class ScrollSizingWidget extends StatefulWidget {
const ScrollSizingWidget({Key? key}) : super(key: key);
@override
State<ScrollSizingWidget> createState() => _ScrollSizingWidgetState();
}
class _ScrollSizingWidgetState extends State<ScrollSizingWidget> {
late final ScrollController _horizontal;
late final ScrollController _vertical;
@override
void initState() {
super.initState();
_horizontal = ScrollController();
_vertical = ScrollController();
}
@override
void dispose() {
_horizontal.dispose();
_vertical.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Scrollbar(
controller: _horizontal,
scrollbarOrientation: ScrollbarOrientation.bottom,
child: SingleChildScrollView(
controller: _horizontal,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.zero,
child: SizedBox(
height: 500,
width: 1000,
child: Scrollbar(
controller: _vertical,
scrollbarOrientation: ScrollbarOrientation.right,
child: SingleChildScrollView(
controller: _vertical,
scrollDirection: Axis.vertical,
child: Column(
children: [
Container(
height: 200,
width: 1000,
color: Colors.red,
),
Container(
height: 1000,
width: 1000,
color: Colors.orange,
),
],
),
),
),
),
),
);
}
首先,您说您的主要 SingleChildScrollView
水平滚动,但您的小部件树以 Scrollbar
开始,它使用垂直 ScrollController
。所以你应该像你解释的那样一步一步地创建你的小部件。
另外,因为你想通过主 SingleChildScrollView
看到垂直 Scrollbar
,我用 Scrollbar
和 SingleChildScrollView
包装了两个(红色和橙色容器)到有你想要的效果。此外,我将这些 Scrollbar
和 SingleChildScrollView
连接到相同的水平 ScrollController
。所以现在,不仅是橙色 Container
,而且两者都可以滚动并粘在一起,而不是独立的。
如果您不希望红色 Container
与橙色 Container
一起滚动,请检查:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: const Scaffold(
body: Center(
child: SafeArea(
child: ScrollSizingWidget(),
),
),
),
);
}
class ScrollSizingWidget extends StatefulWidget {
const ScrollSizingWidget({Key? key}) : super(key: key);
@override
State<ScrollSizingWidget> createState() => _ScrollSizingWidgetState();
}
class _ScrollSizingWidgetState extends State<ScrollSizingWidget> {
late final ScrollController _horizontal;
late final ScrollController _vertical;
@override
void initState() {
super.initState();
_horizontal = ScrollController();
_vertical = ScrollController();
}
@override
void dispose() {
_horizontal.dispose();
_vertical.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Scrollbar(
controller: _horizontal,
scrollbarOrientation: ScrollbarOrientation.bottom,
child: SingleChildScrollView(
controller: _horizontal,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.zero,
child: SizedBox(
height: 500,
width: 1000,
child: Column(
children: [
Container(
height: 200,
width: 1000,
color: Colors.red,
),
Expanded(
child: Scrollbar(
controller: _vertical,
scrollbarOrientation: ScrollbarOrientation.right,
child: SingleChildScrollView(
controller: _vertical,
scrollDirection: Axis.vertical,
child: Container(
height: 700,
width: 1000,
color: Colors.orange,
),
),
),
),
],
),
),
),
);
}
最后,Scrollbar
在 iOS 中的位置由于缺口等原因有点错误。所以我用 SafeArea
包裹了你的 ScrollSizingWidget
来修复iOS.
如果这些答案不是您所期望的,请不要犹豫写信。
编辑:在您在下面的评论中进行解释后,我创建了另一个修复程序。我相信 CustomScrollView
和 Sliver
小部件非常适合这里。红色 Container
,你想留在它的位置,应该用 SliverAppBar
包裹起来。最后,您希望能够垂直滚动的橙色 Container
可以用 SliverFixedExtentList
包裹起来。请检查以下代码:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: const Scaffold(
body: Center(
child: SafeArea(
child: ScrollSizingWidget(),
),
),
),
);
}
class ScrollSizingWidget extends StatefulWidget {
const ScrollSizingWidget({Key? key}) : super(key: key);
@override
State<ScrollSizingWidget> createState() => _ScrollSizingWidgetState();
}
class _ScrollSizingWidgetState extends State<ScrollSizingWidget> {
late final ScrollController _horizontal;
late final ScrollController _vertical;
@override
void initState() {
super.initState();
_horizontal = ScrollController();
_vertical = ScrollController();
}
@override
void dispose() {
_horizontal.dispose();
_vertical.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Scrollbar(
controller: _horizontal,
scrollbarOrientation: ScrollbarOrientation.bottom,
child: SingleChildScrollView(
controller: _horizontal,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.zero,
child: SizedBox(
height: 500,
width: 1000,
child: Scrollbar(
controller: _vertical,
scrollbarOrientation: ScrollbarOrientation.right,
child: CustomScrollView(
controller: _vertical,
scrollDirection: Axis.vertical,
slivers: [
SliverAppBar(
toolbarHeight: 200.0,
collapsedHeight: 200.0,
pinned: true,
stretch: true,
elevation: 0.0,
backgroundColor: Colors.transparent,
title: Container(
height: 200.0,
color: Colors.red,
),
titleSpacing: 0,
),
SliverFixedExtentList(
itemExtent: 1200.0,
delegate: SliverChildBuilderDelegate(
(_, __) => Container(
color: Colors.orange,
),
childCount: 1,
),
),
],
),
),
),
),
);
}