如何获得 ScrollController 的全尺寸

Posted

技术标签:

【中文标题】如何获得 ScrollController 的全尺寸【英文标题】:How to get full size of a ScrollController 【发布时间】:2017-10-23 18:44:23 【问题描述】:

我已将 ScrollController 附加到 [SliverAppBar, SliverList] 的 CustomScrollView

在默认情况下,我会使用 reverse:true 和 animateTo (0.0) 将滚动移动到添加的最后一个元素,但在这种情况下,使用 reverse 也会反转 SliverAppBar/SliverList 的顺序!

所以我想使用 animateTo ( sizeOfScrollableAfterElementAdded ) 但我找不到这个值。

谢谢!

【问题讨论】:

我认为也许将标题更改为 如何以编程方式滚动到 ScrollView 的末尾 会使它更易于访问。 【参考方案1】:

您可以使用_scrollController.position.maxScrollExtent 滚动到末尾。确保在帧后回调中执行此操作,以便它包含您刚刚添加的新项目。

这是一个随着更多项目的添加而滚动到末尾的条形列表示例。

import 'package:flutter/scheduler.dart';
import 'package:flutter/material.dart';

void main() 
  runApp(new MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(),
    );
  


class MyHomePage extends StatefulWidget 
  State createState() => new MyHomePageState();



class MyHomePageState extends State<MyHomePage> 
  ScrollController _scrollController = new ScrollController();

  List<Widget> _items = new List.generate(40, (index) 
    return new Text("item $index");
  );

  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.arrow_downward),
        onPressed: () 
          setState(() 
            _items.add(new Text("item $_items.length"));
          );
          SchedulerBinding.instance.addPostFrameCallback((_) 
            _scrollController.animateTo(
              _scrollController.position.maxScrollExtent,
              duration: const Duration(milliseconds: 300),
              curve: Curves.easeOut,
            );
          );
        ,
      ),
      body: new CustomScrollView(
        controller: _scrollController,
        slivers: [
          new SliverAppBar(
            title: new Text('Sliver App Bar'),
          ),
          new SliverList(
            delegate: new SliverChildBuilderDelegate(
              (context, index) => _items[index],
              childCount: _items.length,
            ),
          ),
        ],
      ),
    );
  

【讨论】:

感谢您让我发现这一点:SchedulerBinding.instance.addPostFrameCallback((_) 这个解决方案完美运行,但是在 initState() 中实现这个呢?例如,在聊天应用程序中,您可能希望在开始时滚动到列表底部。怎样才能做到这一点? @Loolooii 这就是调度程序绑定调用的用途。建立列表并且控制器实际附加到它之后,然后滚动到它的底部。 @ThinkDigital 这个例子中的调度器绑定是onPressed(),对于Loolooii的问题,你如何调度initstate()上的绑定? 对。您只需将其置于 initstate 中即可。并且它安排在当前小部件完成构建时调用它【参考方案2】:

另外,如果您想在开始时立即滚动到列表底部(在 initState() 中),您可以在第一次调用 setState() 之前放置 Collin 解决方案中的以下代码块。

class ExampleState extends State<Example>
    void initState()
    super.initState();

    _scrollController = new ScrollController();

    void _getListItems() async

        //get list items

        SchedulerBinding.instance.addPostFrameCallback((_) 
          _scrollController.animateTo(
          _scrollController.position.maxScrollExtent,
        duration: const Duration(milliseconds: 100),
        curve: Curves.ease,
         );
        );

      setState(()
      );
   
 

【讨论】:

你能在 initState() 中有异步项吗?我以为那是禁止的?也不应该在 setState 之前检查 if(mounted) 吗?但是这看起来有点奇怪//但可能在正确的轨道上 从外观上看,他只是在那里定义了一个函数,但没有调用它。是的,你可以有异步代码,但你不能使用 await,因为 initState() 不能是异步的。我认为在 initstate 中调用 setstate 没有意义,因为该小部件尚未构建,因此它最初应该使用正确的值构建 根据你的回答我创建了这个类来滚动到列表视图的末尾或顶部***.com/a/68983662/11567596

以上是关于如何获得 ScrollController 的全尺寸的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 使用 StreamBuilder 从 firebase 获取数据后,如何使用 ScrollController 跳转到列表视图的底部?

vuetify.js 如何获得 v-container 的全宽

如何在响应式表格中获得文本左对齐的全宽列

FlutterListView 列表高级功能 ( ScrollController 上拉加载更多 )

Flutter 可滚动组件:ScrollController

如何检测ListView项的位置?