当大家进行Flutter开发做项目后,难免会遇到滚动文字的需求,类似于广告循环播放。
将会用到两个知识点:
1、ScrollController
ScrollController间接继承自Listenable,我们可以根据ScrollController来监听滚动事件,
可以用ScrollController来控制可滚动组件的滚动位置
offset 可滚动组件 当前的滚动位置
jumpTo 跳转到指定的位置
animateTo 跳转到指定的位置 ,跳转时会执行一个动画
dispose 为了避免内存泄露,需要调用 controller.dispose
2、Timer
需要使用到定时Timer进行动画的滚动,Flutter Timer 使用过程中可能在页面销毁或应用进入后台时,忘记取消 Timer,一定要在dispose的时候关闭Timer。
实现步骤如下:
1、dispose记得销毁Timer防止溢出
//文字滚动效果
class FontMarquee extends StatefulWidget {
final List
final double marqueeHeight;
const FontMarquee(this.detialWidget, {this.marqueeHeight});
@override
FontMarqueeState createState() => FontMarqueeState();
}
class FontMarqueeState extends State with WidgetsBindingObserver
{
ScrollController _controller;
int height = 0;
Timer _timer;
@override void dispose() {
_controller.dispose();
cancelTimer();
super.dispose();
}
void cancelTimer() {
if (_timer != null) { _timer.cancel(); }
}
2、在init方法里面定义动画逻辑
@override
void initState() {
final WidgetsBinding widgetsBinding = WidgetsBinding.instance;
widgetsBinding.addPostFrameCallback((callback) {
_timer = Timer.periodic(const Duration(seconds: 3), (timer) {
height += widget?.marqueeHeight?.toInt() ?? 55;
_controller.animateTo((height).toDouble(),
duration: const Duration(seconds: 2), curve: Curves.easeOutSine);
int marqueeHeight = widget?.marqueeHeight?.toInt() ?? 55;
if (height >= marqueeHeight * widget?.detialWidget?.length) {
_controller.jumpTo(0);
height = 0;
}
});
});
_controller = new ScrollController(initialScrollOffset: 0);
super.initState();
}
3、build方法里面加入ListView
@override
Widget build(BuildContext context) {
return Container(
height: widget?.marqueeHeight ?? 55,
child: ListView.builder(
//禁止手动滑动
physics: const NeverScrollableScrollPhysics(),
itemCount: widget?.detialWidget?.length,
//item固定高度
itemExtent: widget?.marqueeHeight ?? 55,
scrollDirection: Axis.vertical,
controller: _controller,
itemBuilder: (context, index) {
return Container(
child: widget?.detialWidget[index] ?? Container(),
);
}),
);
}