展开图块时如何滚动ExpansionTile / Listview?

问题描述 投票:1回答:2

我们在ExpansionTile中有一堆ListView(到目前为止还不太疯狂,对吧?)。我们的用户希望我们在打开ExpansionTile时“自动滚动”列表,因此新的展开图块现在位于屏幕的顶部(或尽可能顶部),因此他们不必手动滚动查看我们刚刚打开的内容。

[我认为我们需要ScrollController上的ListView之类的东西-并注册onExpansionChanged ..来执行.. something。这对我来说还不算什么。 :)

任何有关如何执行此操作的指针或帮助,将不胜感激!

TIA!

dart flutter flutter-layout
2个回答
4
投票

如果我对您的要求是正确的,基本上是一种自动向上滚动ExpansionTile的方法,因此用户不必手动进行操作即可查看其内容,对吧?

然后,您实际上可以在ScrollController中使用ListView,并利用onExpansionChangedExpansionTile回调将其向上/向下滚动,从而根据图块的大小与其当前位置进行相应的滚动。

但是现在您想知道:我怎么知道要滚动多少?

为此,您要么通过赋予一些约束(例如,构建Container(heigh: 100.0))来预先知道构建窗口小部件时的高度是多少,要么在这种特定情况下,您不知道[[因此,我们可以使用ExpansionTile,然后通过在运行时检查GlobalKey来检查其渲染高度,以<知道折叠时需要多少像素并将其乘以索引。 RenderBox

确定,现在我们有了一个  ExpansionTile _buildExpansionTile(int index) {
    final GlobalKey expansionTileKey = GlobalKey();
    double previousOffset;

    return ExpansionTile(
      key: expansionTileKey,
      onExpansionChanged: (isExpanded) {
        if (isExpanded) previousOffset = _scrollController.offset;
        _scrollToSelectedContent(isExpanded, previousOffset, index, expansionTileKey);
      },
      title: Text('My expansion tile $index'),
      children: _buildExpansionTileChildren(),
    );
  }
,它将在其生成器中将这个ListView_buildExpansionTile一起使用。展开图块时,我们还保存了GlobalKey的滚动偏移量。但是,实际上我们如何向上滚动以显示其内容?让我们看看ListView方法。

_scrollToSelectedContent

因此,我们通过其键访问渲染对象,然后使用  void _scrollToSelectedContent(bool isExpanded, double previousOffset, int index, GlobalKey myKey) {
    final keyContext = myKey.currentContext;

    if (keyContext != null) {
      // make sure that your widget is visible
      final box = keyContext.findRenderObject() as RenderBox;
      _scrollController.animateTo(isExpanded ? (box.size.height * index) : previousOffset,
          duration: Duration(milliseconds: 500), curve: Curves.linear);
    }
  }
滚动控制器在展开时向上滚动,在折叠时通过将其高度乘以索引来向下滚动回到其初始位置。您不必回滚,这只是我个人对本示例的偏爱。这将导致如下所示:

ListView

这里有example中的完整示例

StatefulWidget


0
投票
基于import 'package:flutter/material.dart'; void main() => runApp(MaterialApp(home: MyApp())); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { final ScrollController _scrollController = ScrollController(); void _scrollToSelectedContent(bool isExpanded, double previousOffset, int index, GlobalKey myKey) { final keyContext = myKey.currentContext; if (keyContext != null) { // make sure that your widget is visible final box = keyContext.findRenderObject() as RenderBox; _scrollController.animateTo(isExpanded ? (box.size.height * index) : previousOffset, duration: Duration(milliseconds: 500), curve: Curves.linear); } } List<Widget> _buildExpansionTileChildren() => [ FlutterLogo( size: 50.0, ), Text( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse vulputate arcu interdum lacus pulvinar aliquam. Donec ut nunc eleifend, volutpat tellus vel, volutpat libero. Vestibulum et eros lorem. Nam ut lacus sagittis, varius risus faucibus, lobortis arcu. Nullam tempor vehicula nibh et ornare. Etiam interdum tellus ut metus faucibus semper. Aliquam quis ullamcorper urna, non semper purus. Mauris luctus quam enim, ut ornare magna vestibulum vel. Donec consectetur, quam a mattis tincidunt, augue nisi bibendum est, quis viverra risus odio ac ligula. Nullam vitae urna malesuada magna imperdiet faucibus non et nunc. Integer magna nisi, dictum a tempus in, bibendum quis nisi. Aliquam imperdiet metus id metus rutrum scelerisque. Morbi at nisi nec risus accumsan tempus. Curabitur non sem sit amet tellus eleifend tincidunt. Pellentesque sed lacus orci.', textAlign: TextAlign.justify, ), ]; ExpansionTile _buildExpansionTile(int index) { final GlobalKey expansionTileKey = GlobalKey(); double previousOffset; return ExpansionTile( key: expansionTileKey, onExpansionChanged: (isExpanded) { if (isExpanded) previousOffset = _scrollController.offset; _scrollToSelectedContent(isExpanded, previousOffset, index, expansionTileKey); }, title: Text('My expansion tile $index'), children: _buildExpansionTileChildren(), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('MyScrollView'), ), body: ListView.builder( controller: _scrollController, itemCount: 100, itemBuilder: (BuildContext context, int index) => _buildExpansionTile(index), ), ); } } 的答案,您可以通过从其控制器获取ListView的当前滚动偏移量来计算滚动所需的数量:
© www.soinside.com 2019 - 2024. All rights reserved.