问题:
在使用Flutter的ListView等滚动组件做历史记录或日志记录时,需要在更新内容后立即定位到内容底部(默认是在顶部的)。
寻找解决方案:
- ListView有一个reverse属性,如果把内容倒置,倒是可以总显示新内容。
但问题是内容少的时候,是直接靠底部显示的,这样看起来比较怪。
- ListView的ScrollController本身提供了像素滚动的方法,可以计算视口高度和内容总高度,然后调用Controller的jumpTo或animateTo
这是一个临时解决方案,需要测量出当前视口的高度,然后写在代码里,内容的高度根据子元素数目计算,需要子元素内容没太大差异,等高的情况就好控制
在Windows下效果尚可,但到苹果设备上由于物理滚动的特性,会很跳脱
- 找到一个新Controller可以控制滚动到当前选中的组件FixedExtentScrollController
原来是场误会,这个控制器是专门给新组件ListWheelScrollView用的,这是一个齿轮滚动选择的组件,被选中项总是在中间
最终方案:
最后通过print ScrollController.position这个属性,发现它在运行中其实是ScrollPositionWithSingleContext的实例,这个实例可以直接获取到滚动组件的视口高度,可滚动范围等参数。
只需要做一个强制类型转换就可以了
演示代码
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo For ListView'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
ScrollController controller;
@override
void initState() {
super.initState();
controller = ScrollController();
}
void _incrementCounter() {
setState(() {
_counter++;
});
Future.delayed(Duration(milliseconds: 16)).then((value) =>
controller.animateTo(
(controller.position as ScrollPositionWithSingleContext)
.maxScrollExtent,
duration: Duration(milliseconds: 200),
curve: Curves.easeOutQuart));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Container(
width: 150,
height: 300,
decoration: BoxDecoration(
border: Border.all(color: Colors.black26, width: 0.5)),
child: ListView(
controller: controller,
padding: EdgeInsets.all(10),
children: List<Widget>.generate(
_counter, (index) => Text('This is row $index')),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END