【问题标题】:Reset Flutter CustomScrollView on state change在状态更改时重置 Flutter CustomScrollView
【发布时间】:2019-10-13 13:26:08
【问题描述】:

我正在构建一个垂直滚动的日历,并且我已经将我的日子实现为多个 SliverLists,这样我就可以专注于某一天,同时仍然有过去和未来的日子。

问题是,当focusDate 通过父项中的状态更改发生更改时,列表会正确更新日期,但会保持其滚动位置。例如,如果我滚动到列表顶部,则更改 focusDate 日期更新,但我仍然位于列表顶部。

我希望完全替换 focusDate 更改时的列表(不仅仅是日期)。当从日期选择器中选择日期时会发生这种情况。因此,无论如何都需要获取新数据,并且可以创建一个新的CustomScrollView 并专注于正确的日期。

import 'package:flutter/material.dart';

import 'day.dart';

class DaysManager extends StatelessWidget {
  List<Day> days;

  DaysManager({DateTime focusDate}) {
    final DateTime startDate = focusDate.subtract(Duration(days: 30));
    days = List.generate(61, (int index) {
      return Day(
        date: startDate.add(Duration(days: index)),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return _buildScrollView();
  }

  CustomScrollView _buildScrollView() {
    final focusKey = ValueKey('focus');

    return CustomScrollView(
      center: focusKey,
      slivers: <Widget>[
        SliverList(
          delegate: SliverChildListDelegate(
            days.sublist(0, 31).reversed.toList(),
          ),
        ),
        SliverList(
          key: focusKey,
          delegate: SliverChildListDelegate(
            days.sublist(31, 32),
          ),
        ),
        SliverList(
          delegate: SliverChildListDelegate(
            days.sublist(32),
          ),
        ),
      ],
    );
  }
}

【问题讨论】:

    标签: flutter dart flutter-sliver


    【解决方案1】:

    您可以将 ScrollController 添加到您的 CustomListView。当你设置你的状态时,使用控制器动画到你刚刚选择的位置。

    ScrollController 有一个方法:

    Future<Void> animateTo(
      double offset, {
      @required Duration duration,
      @required Curve curve,
    })
    

    其中 offset 是您要设置动画的位置。

    【讨论】:

    • 我看到了一些对此的引用,但我不确定该控制器方法应该去哪里。 setState 是从父类调用的。我正在构建列表,但是在构建和返回之间我应该在哪里调用 animateTo
    • 另外,为什么我不能有一个新的?当日子改变并且发生滚动时,似乎看起来很糟糕。我只是想让这个东西完全重新初始化。
    • 将控制器声明为类变量,然后在CustomScrollView中将控制器传入名为“controller”的参数中。当您在更新列表后在该方法中执行 setState 时,使用您的控制器对象调用 animateTo 方法
    • 你的 DaysManager 类是无状态的。我相信您在调用 set state 的 StatefulWidget 中使用它。当您调用 setState 时,您的 DaysManager 应该使用新数据而不是旧数据进行重建。您能否展示一些您正在尝试实现的屏幕截图。
    • 完全正确,它确实用新数据重建。但它保持其滚动位置。如,它正在替换数据,但不重置滚动。
    【解决方案2】:
            ScrollController _scrollController;
            @override
            void initState() {
              super.initState();
              _scrollController = new ScrollController();
            }
    
            @override
            Widget build(BuildContext context) {
              return ListView.builder(itemBuilder: (context, index){
                return FlatButton(onPressed: (){
                  _scrollController.animateTo(index*(YOUR_VIEW_HEIGHT), duration: new Duration(seconds: 2), curve: Curves.ease);
                }, child: Text("Item   $index"));
              }, controller: _scrollController,);
            }
    

    【讨论】:

    • @WillLuce 按钮仅供参考,您的视图将位于按钮的位置。
    猜你喜欢
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 2019-09-27
    • 2021-06-29
    • 2020-10-01
    • 1970-01-01
    • 2021-06-27
    相关资源
    最近更新 更多