简体   繁体   English

如何使用 Flutter 中的 StatelessWidget 和提供程序以编程方式滚动 ListView?

[英]How to scroll a ListView programmatically with StatelessWidget and provider in Flutter?

According to many Flutter provider tutorials, it is recommended to use StatelessWidget instead of StatefulWidget with provider.根据很多 Flutter provider 教程,建议使用 StatelessWidget 而不是 StatefulWidget with provider。 But I can't find a way to scroll ListView when using StatelessWidget.但是在使用 StatelessWidget 时我找不到滚动 ListView 的方法。

Suppose we have a ListView with many lines of text, which can be dynamically appended, and should always scroll to the middle line.假设我们有一个包含多行文本的 ListView,可以动态附加,并且应该始终滚动到中间行。 Like this:像这样:

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

class MyData with ChangeNotifier {
  List<String> _lines = [];
  MyData() {
    for (int i = 0; i < 100; i++) {
      _lines.add("line $i");
    }
  }

  List<String> get lines => _lines;
  void add(line) {
    _lines.add(line);
    notifyListeners();
  }
}

void main() {
  MyData data = new MyData();
  final app = ChangeNotifierProvider<MyData>.value(value: data, child: MyApp());
  runApp(app);
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.dark(),
      home: MyHomePage(),
    );
  }
}

class DataPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _data = Provider.of<MyData>(context);
    return Scaffold(
        appBar: AppBar(),
        body: ListView.builder(
            itemCount: _data.lines.length,
            itemBuilder: (context, index) {
              return Text(_data.lines[index]);
            }));
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _data = Provider.of<MyData>(context);
    return Scaffold(
        appBar: AppBar(
          actions: <Widget>[
            IconButton(
                icon: Icon(Icons.add),
                onPressed: () {
                  _data.add("new line");
                })
          ],
        ),
        body: Center(child: Text("${_data.lines.length} lines")),
        floatingActionButton: FloatingActionButton(
          onPressed: () => Navigator.of(context)
              .push(MaterialPageRoute(builder: (context) => DataPage())),
          child: Icon(Icons.list),
        ));
  }
}

Is there any way to keep scroll to the middle of the ListView when new line added?添加新行时,有什么方法可以保持滚动到 ListView 的中间?

with WidgetsBinding.instance, scrollTo calls after the widget ist build.使用 WidgetsBinding.instance,在构建小部件后调用 scrollTo。 Everytime when the Provider MyData send a notify每次 Provider MyData 发送通知时

i hope that's ok for you, height is a requirement我希望这对你没问题,身高是一个要求

class DataPage extends StatelessWidget {

  final _controller = ScrollController();
  final _height = 30.0;

  @override
  Widget build(BuildContext context) {
    final _data = Provider.of<MyData>(context);

    scrollTo() {
      print(_data.lines.length);
      _controller.jumpTo(_data.lines.length / 4 * _height);
    }

    WidgetsBinding.instance
        .addPostFrameCallback((_) => scrollTo());

    return Scaffold(
        appBar: AppBar(),
        body: ListView.builder(
          controller: _controller,
            itemCount: _data.lines.length,
            itemBuilder: (context, index) {
              return new Container(child: Text(_data.lines[index]), height: _height,);
            }));
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM