如何在 Flutter 中使用 StatelessWidget 和提供程序以编程方式滚动 ListView?
How to scroll a ListView programmatically with StatelessWidget and provider in Flutter?
根据很多Flutter provider教程,推荐使用StatelessWidget而不是StatefulWidget with provider。
但是我在使用 StatelessWidget 时找不到滚动 ListView 的方法。
假设我们有一个包含多行文本的 ListView,可以动态追加,并且应该始终滚动到中间一行。像这样:
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),
));
}
}
有什么方法可以在添加新行时保持滚动到 ListView 的中间?
with WidgetsBinding.instance,scrollTo 在 widget ist 构建后调用。
每次 Provider MyData 发送通知时
我希望你没问题,身高是有要求的
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,);
}));
}
}
根据很多Flutter provider教程,推荐使用StatelessWidget而不是StatefulWidget with provider。 但是我在使用 StatelessWidget 时找不到滚动 ListView 的方法。
假设我们有一个包含多行文本的 ListView,可以动态追加,并且应该始终滚动到中间一行。像这样:
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),
));
}
}
有什么方法可以在添加新行时保持滚动到 ListView 的中间?
with WidgetsBinding.instance,scrollTo 在 widget ist 构建后调用。 每次 Provider MyData 发送通知时
我希望你没问题,身高是有要求的
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,);
}));
}
}