【问题标题】:SingleChildScrollView + Controller - Page resets to top when resizing windowSingleChildScrollView + Controller - 调整窗口大小时页面重置为顶部
【发布时间】:2022-11-01 11:01:04
【问题描述】:

我正在创建一个颤动的 Web 应用程序,但是在使用 SingleChildScrollView + ScrollController 调整窗口大小时遇到​​问题。

当我调整浏览器窗口的大小时,页面“捕捉”到最顶部。作为一个网络应用程序,大部分页面“部分”都是由列组成的,具有响应编码的小部件作为子级,具有灵活或扩展等小部件。根据我的阅读,SingleChildScrollView 小部件不适用于灵活或扩展小部件,所以我认为这可能是我的问题。

出于测试目的,我创建了一个新页面,其中包含一个高度为 3000 的 SizedBox,它允许我滚动。滚动到底部并调整窗口大小后,我仍然被抢到页面顶部。因此,无论是否使用 Expanded 或 Flexible 小部件,我都会得到相同的结果。

仅使用 SizedBox 进行测试

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      color: Colors.white,
      body: SingleChildScrollView(
        controller: controller.scrollController,
        primary: false,
        child: Column(
          children: [
            SizedBox(
              width: 150,
              height: 3000,
            ),
          ],
        ),
      ),
    );
  }

我在这个项目中使用 Getx 以尝试在我仍在学习核心概念的同时更快地启动和运行演示应用程序。下面是我的控制器。

控制器

class HomePageScrollControllerX extends GetxController {
  late ScrollController scrollController;

  @override
  void onInit() {
    super.onInit();

    scrollController = ScrollController(
      initialScrollOffset: 0.0,
      keepScrollOffset: true,
    );
    
  }
}

预先感谢您对此主题的任何见解!

编辑

我在我的 ScrollController 上添加了一个监听器,它能够打印到我正在滚动的控制台。但是,当我调整窗口大小(在 Chrome 和 Edge 中测试)时,不会调用侦听器。

目前,我相信我唯一的选择是使用侦听器来更新控制器中的“偏移”变量,并在小部件重建时将窗口的宽度传递给控制器​​。如果操作正确,我应该能够使用控制器滚动到保存的偏移量。像这样的东西:

if (scrollController.hasClients) {
  if (offset > scrollController.position.maxScrollExtent) {
    scrollController.jumpTo(scrollController.position.maxScrollExtent);
  } else if (offset < scrollController.position.minScrollExtent) {
    scrollController.jumpTo(scrollController.position.minScrollExtent);
  } else {
    scrollController.jumpTo(offset);
  }
}

然而,我觉得这不应该是必要的——我敢打赌这个解决方案对用户来说是显而易见的。

编辑 2

虽然我确实在 return 语句之前添加了以下代码,但我最初的想法似乎是正确的。当我抓住窗口的边缘并移动它时,它会弹出到窗口的顶部,然后会跳转到正确的滚动位置。它看起来绝对可怕!

  @override
  Widget build(BuildContext context) {
    Future.delayed(Duration.zero, () {
      controller.setWindowWithAndScroll(MediaQuery.of(context).size.width);
    });
    return PreferredScaffold(
      color: Colors.white,
      body: SingleChildScrollView(
        controller: controller.scrollController,
    ......

【问题讨论】:

    标签: flutter flutter-web flutter-getx scrollcontroller


    【解决方案1】:

    我通过将 scrollController 初始化为控制器类之外的最终变量来实现您的代码而无需 getX。我在 microsoft edge 上运行它并没有遇到您描述的问题。导致您的问题的原因很可能是您使用 getX 处理状态管理的方式。我猜您的 onInit 函数在您调整网页大小时会运行多次,这就是页面快速备份的原因。我建议记录调用 onInit 函数的次数。

    【讨论】:

    • 感谢您对此的见解。我确实看了一下,onInit() 函数只被调用一次。在 onInit() 中,我向滚动控制器添加了一个侦听器,用于打印(“检测到滚动”)。当我滚动时,打印语句被添加到控制台中。我相信这可能只是保存职位的问题?
    猜你喜欢
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2011-08-18
    • 2011-03-07
    • 1970-01-01
    相关资源
    最近更新 更多