【问题标题】:Flutter, ListView, How to add several items on top of the ListView and make it not scroll to the topFlutter,ListView,如何在ListView顶部添加几个项目并使其不滚动到顶部
【发布时间】:2019-12-17 10:25:59
【问题描述】:

当我在ListView 顶部添加一些项目时,它会滚动到0 索引上的顶部项目。但我需要它保持与添加项目之前相同的位置。

例如,消息列表顶部的聊天历史分页,如果我打开任何信使(Telegram、WhatsApp 等),打开历史悠久的聊天并向下滚动下载历史。历史将被添加到列表的顶部(从服务器一次约 20 条消息),但列表将保持在同一位置(滚动时)。

如果你添加到底部,Flutter ListView 的行为就像这样,但是如果你添加到顶部,它会跳转到第一个添加的项目。我希望它留下来。

【问题讨论】:

    标签: flutter dart flutter-layout


    【解决方案1】:

    截图:


    由于您没有分享任何代码,我只是创建了一个简单的演示来展示如何实现类似于消息传递应用程序的效果。代码很简单易懂,我几乎到处都用过cmets。

    代码(Null 安全):

    class _MyPageState extends State<MyPage> {
      // Say you have total 100 messages, and you want to load 20 messages on each scroll.
      final int _totalMessages = 100, _loadInterval = 20;
      final double _loadingOffset = 20;
      late final List<String> _messages;
      bool _loading = false;
      final ScrollController _controller = ScrollController();
    
      @override
      void initState() {
        super.initState();
    
        // Initially, load only 20 messages.
        _messages = List.generate(20, (i) => 'Message   #${_totalMessages - i}');
        _controller.addListener(_scrollListener);
      }
    
      void _scrollListener() async {
        var max = _controller.position.maxScrollExtent;
        var offset = _controller.offset;
    
        // Reached at the top of the list, we should make _loading = true
        if (max - offset < _loadingOffset && !_loading) {
          _loading = true;
    
          // Load 20 more items (_loadInterval = 20) after a delay of 2 seconds
          await Future.delayed(Duration(seconds: 2));
          int lastItem = _totalMessages - _messages.length;
          for (int i = 1; i <= _loadInterval; i++) {
            int itemToAdd = lastItem - i;
            if (itemToAdd >= 0) _messages.add('Message   #$itemToAdd');
          }
    
          // Items are loaded successfully, make _loading = false
          setState(() {
            _loading = false;
          });
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('Messages')),
          body: ListView.builder(
            controller: _controller,
            reverse: true,
            itemCount: _messages.length + 1, // +1 to show progress indicator.
            itemBuilder: (context, index) {
              // All messages fetched. 
              if (index == _totalMessages) return Container();
    
              // Reached top of the list, show a progress indicator. 
              if (index == _messages.length) return Align(child: CircularProgressIndicator());
    
              // Show messages. 
              return ListTile(title: Text('${_messages[index]}'));
            },
          ),
        );
      }
    }
    

    【讨论】:

    • 是的!就是这样:反向:真;谢谢!我可以在 12 小时内奖励赏金。等一下;)
    • 我有一个类似的问题,但只是设置 reverse : true 并不能解决它,因为我的列表可以从顶部和底部增长。 5天以来一直在苦苦挣扎,有什么建议吗?
    【解决方案2】:

    @CopsOnRoad 提出的解决方案适用于您的提要只能向一个方向扩展。

    This 解决方案适用于将项目附加到列表的顶部和底部。解决方案的思路如下。您创建两个 SliverList 并将它们放在 CustomScrollView 中。

    CustomScrollView(
      center: centerKey,
      slivers: <Widget>[
        SliverList(
          delegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) {
                return Container(
                  // Here we render elements from the upper group
                  child: top[index]
                )
            }
        ),
        SliverList(
          // Key parameter makes this list grow bottom
          key: centerKey,
          delegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) {
                return Container(
                  // Here we render elements from the bottom group
                  child: bottom[index]
                )
            }
        ),
    )
    

    第一个列表向上滚动,而第二个列表向下滚动。它们的偏移零点固定在同一点,从不移动。如果您需要添加一个项目,请将其推送到顶部列表,否则,将其推送到底部列表。这样他们的偏移量就不会改变,你的滚动视图也不会跳跃。 您可以在following dartpad 示例中找到解决方案原型。

    【讨论】:

      猜你喜欢
      • 2021-04-25
      • 2020-11-18
      • 1970-01-01
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多