水平滚动视图中的 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,我用 ScrollbarSingleChildScrollView 包装了两个(红色和橙色容器)到有你想要的效果。此外,我将这些 ScrollbarSingleChildScrollView 连接到相同的水平 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.

中的问题

如果这些答案不是您所期望的,请不要犹豫写信。

编辑:在您在下面的评论中进行解释后,我创建了另一个修复程序。我相信 CustomScrollViewSliver 小部件非常适合这里。红色 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,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      );
}