| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- 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<AutoScrollListView> createState() => _AutoScrollListViewState();
- }
- class _AutoScrollListViewState extends State<AutoScrollListView> {
- 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<UserScrollNotification>(
- 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,
- ),
- );
- }),
- );
- }
- }
|