一尘不染

如何自动滚动到网格视图的末尾?

flutter

当我将项目添加到网格视图的末尾时,我希望用户看到已添加的内容。这是我的意思的示例:

屏幕截图

用户通过按+图标添加项目。问题在于,在第14项之后,没有反馈表明已添加任何项。将其添加到列表后,如何自动滚动到最后一项?

(加分点:将第n个项目添加到列表中间时,如何滚动至该项目)

这是滚动到列表视图末尾的答案,但是如果我反转列表的顺序,那么有时在第一行的“缺失”项会显得很奇怪。

这是我的代码:

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',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    List items = [];
    for (int i = 0; i < _counter; i++) {
      items.add(new Text("Item $i"));
    }
    return new Scaffold(
      appBar: new AppBar(title: new Text("Scroll To End Test")),
      body: new GridView.extent(
        primary: true,
        maxCrossAxisExtent: 150.0,
        children: items,
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          setState(() {
            _counter++;
          });
        },
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ),
    );
  }
}

阅读 230

收藏
2020-08-13

共1个答案

一尘不染

声明一个滚动控制器,然后使用它来移动到所需的位置。这是滚动到最后一个元素的示例。请注意,滚动控制器已显式声明,因此您无法发出primary: true

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',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  ScrollController _scrollController;                                 // NEW

  @override                                                           // NEW
  void initState() {                                                  // NEW
    super.initState();                                                // NEW
    _scrollController = new ScrollController(                         // NEW
      initialScrollOffset: 0.0,                                       // NEW
      keepScrollOffset: true,                                         // NEW
    );
  }

  void _toEnd() {                                                     // NEW
    _scrollController.animateTo(                                      // NEW
      _scrollController.position.maxScrollExtent,                     // NEW
      duration: const Duration(milliseconds: 500),                    // NEW
      curve: Curves.ease,                                             // NEW
    );                                                                // NEW
  }                                                                   // NEW

  @override
  Widget build(BuildContext context) {
    List items = [];
    for (int i = 0; i < _counter; i++) {
      items.add(new Text("Item $i"));
    }
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Scroll To End Test"),
        actions: <Widget>[                                            // NEW
          new IconButton(                                             // NEW
              icon: new Icon(Icons.arrow_downward), onPressed: _toEnd)// NEW
        ],                                                            // NEW
      ),
      body: new GridView.extent(
        //primary: true, // REMOVED
        maxCrossAxisExtent: 150.0,
        children: items,
        controller: _scrollController,                                // NEW
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          setState(() {
            _counter++;
          });
        },
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ),
    );
  }
}

关于“奖励点”,我对ScrollControllers不太熟练,但是据我所知,该.animateTo( )方法要求将double作为第一个输入,在那里设置滚动点:原则上,将要滚动 的第i个 项目放到

var cursor = i/(# items) * _scrollController.position.maxScrollExtent

根据网格每行有多少个对象来调整此值。我知道这只是一个草图,但我认为它可以带您到那里。

2020-08-13