import 'dart:async'; import 'package:flutter/cupertino.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; class AutoScrollListView extends StatefulWidget { final NullableIndexedWidgetBuilder itemBuilder; final int itemCount; final Axis scrollDirection; final EdgeInsetsGeometry? padding; final bool isAutoScrolling; const AutoScrollListView({ super.key, required this.itemBuilder, required this.itemCount, this.padding, this.isAutoScrolling = true, this.scrollDirection = Axis.horizontal, }); @override State createState() => _AutoScrollListViewState(); } class _AutoScrollListViewState extends State { final ScrollController scrollController = ScrollController(); Timer? _timer; bool _isUserScrolling = true; @override void initState() { super.initState(); _isUserScrolling = widget.isAutoScrolling; _startAutoScroll(); } @override void dispose() { super.dispose(); scrollController.dispose(); _timer?.cancel(); } void _startAutoScroll() { _timer = Timer.periodic(Duration(milliseconds: 50), (timer) { if (!_isUserScrolling || !scrollController.hasClients) return; final maxScrollExtent = scrollController.position.maxScrollExtent; final current = scrollController.position.pixels; double next = current + 1; if (next >= maxScrollExtent) { next = 0; } scrollController.jumpTo(next); }); } void _onUserScroll() { if (!_isUserScrolling) { return; } _timer?.cancel(); _timer = Timer(Duration(seconds: 1), () { setState(() { _isUserScrolling = widget.isAutoScrolling; }); _startAutoScroll(); }); } @override Widget build(BuildContext context) { return NotificationListener( onNotification: (notification) { if (notification.direction != ScrollDirection.idle) { _onUserScroll(); // 用户滑动时暂停自动滚动 } return false; // 不阻止子组件的事件传递 }, child: ListView.builder( padding: widget.padding, scrollDirection: widget.scrollDirection, itemCount: 1000000, itemBuilder: (context, index) { return widget.itemBuilder(context, index % widget.itemCount); }, controller: scrollController, ), ); } } // 多行横向自动滚动列表 /// 一个支持自动滚动的多行横向列表,每一行自动向右滚动(模拟跑马灯效果) class StaggeredAutoScrollListView extends StatelessWidget { final NullableIndexedWidgetBuilder itemBuilder; final int itemCount; final EdgeInsetsGeometry? padding; final bool isAutoScrolling; final int rowCount; final int loopFactor; final double rowHeight; const StaggeredAutoScrollListView({ super.key, required this.itemBuilder, required this.itemCount, this.padding, this.isAutoScrolling = true, this.rowCount = 3, this.loopFactor = 3, this.rowHeight = 50.0, }); @override Widget build(BuildContext context) { final itemsPerRow = (itemCount / rowCount).ceil(); return Column( children: List.generate(rowCount, (rowIndex) { final startIndex = rowIndex * itemsPerRow; final endIndex = (startIndex + itemsPerRow).clamp(0, itemCount); final rowItems = List.generate(endIndex - startIndex, (i) => startIndex + i); final extendedItems = List.generate( rowItems.length * loopFactor, (i) => rowItems[i % rowItems.length], ); return SizedBox( height: rowHeight.w, child: AutoScrollListView( itemBuilder: (context, index) => itemBuilder(context, extendedItems[index]), itemCount: extendedItems.length, scrollDirection: Axis.horizontal, isAutoScrolling: isAutoScrolling, padding: padding, ), ); }), ); } }