import 'package:atui/generated/l10n.dart';
import 'package:atui/jade/configs/PathConfig.dart';
import 'package:atui/jade/experienceStation/ExperienceStationListTwo.dart';
import 'package:atui/jade/market/MarketExpBannerItemView.dart';
import 'package:atui/jade/market/MarketExpGoodsListPage.dart';
import 'package:atui/jade/market/MarketPromoExpBannerItemView.dart';
import 'package:atui/jade/market/promotionExpress/MarketProductSelectionBannerItemView.dart';
import 'package:atui/jade/market/promotionExpress/PromotionExpress.dart';
import 'package:atui/jade/utils/JadeColors.dart';
import 'package:atui/model/home/recommend_model.dart';
import 'package:atui/model/main_model.dart';
import 'package:atui/pages/login_page.dart';
import 'package:atui/util/easy_loading_util.dart';
import 'package:atui/util/login_util.dart';
import 'package:atui/util/navigator_util.dart';
import 'package:atui/util/provider_util.dart';
import 'package:card_swiper/card_swiper.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
/*
* 商城主页面促销速递、体验购轮播、选品广场 走马灯
* */
class SmoothInfiniteScroll extends StatefulWidget {
final RecommendModel recommendModel;
const SmoothInfiniteScroll(this.recommendModel);
State<SmoothInfiniteScroll> createState() => _SmoothInfiniteScrollState();
}
class _SmoothInfiniteScrollState extends State<SmoothInfiniteScroll> with SingleTickerProviderStateMixin {
late ScrollController _scrollController;
late AnimationController _animationController;
late Animation<double> _animation;
// 原始数据
late final List<Widget> _originalItems;
late List<Widget> _items; // 翻倍后的数据
// 配置参数
final double _itemWidth = 220;
final double _itemSpacing = 10;
final Duration _scrollDuration = const Duration(seconds: 45); // 滚动一轮时间
// 原始数据总宽度(用于判断过渡点)
double get _originalTotalWidth => _originalItems.length * (_itemWidth + _itemSpacing);
void initState() {
super.initState();
_originalItems = [_promoBanner(), _aTuiExpBanner(),_productSelectionBanner()];
_items = [..._originalItems, ..._originalItems..._originalItems]; // 数据翻倍,消除滚动到最后一条继续滚动出现空白区域跳回开头产品明显滚动断层问题,结合位置重置(jumpTo())实现无缝衔接
_scrollController = ScrollController()
..addListener(_handleScroll);
// 动画控制器(匀速滚动)
_animationController = AnimationController(
vsync: this,
duration: _scrollDuration,
);
// 线性动画(确保速度均匀)
_animation = CurvedAnimation(
parent: _animationController,
curve: Curves.linear,
)..addListener(() {
if (_scrollController.hasClients) {
// 计算目标位置(基于动画进度)
final maxExtent = _scrollController.position.maxScrollExtent;
final target = _animation.value * maxExtent;
_scrollController.jumpTo(target);
}
});
_animationController.repeat();
}
// 处理滚动:平滑过渡替代生硬跳转
void _handleScroll() {
if (!_scrollController.hasClients) return;
final currentOffset = _scrollController.offset;
// 当滚动超过原始数据总宽度时,计算偏移差并平滑过渡
if (currentOffset >= _originalTotalWidth) {
// 计算当前位置与原始数据末尾的差值(这部分是需要衔接的偏移量)
final offsetDiff = currentOffset - _originalTotalWidth;
// 平滑滚动到差值位置(视觉上相当于从末尾回到开头的偏移处)
_scrollController.animateTo(
offsetDiff,
duration: Duration(microseconds: 1), // 瞬间过渡(视觉无感知)
curve: Curves.linear,
);
}
}
void dispose() {
_scrollController.dispose();
_animationController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return /*MouseRegion(
opaque: false,
onEnter: (_) => _animationController.stop(), // 悬停暂停
onExit: (_) => _animationController.repeat(), // 离开继续
child: ,
)*/
Container(
height: 320.w,
margin: EdgeInsets.only(left: 30.w,right: 30.w,top: 30.w),
padding: EdgeInsets.only(left: 15.w,right: 15.w,top: 20.w,bottom: 20.w),
decoration: BoxDecoration(
color: Colors.white,
image: DecorationImage(
image: AssetImage(PathConfig.imageMarketPromoExpBg),
fit: BoxFit.fill
),
boxShadow: [BoxShadow(color: JadeColors.grey_6,blurRadius: 1.0,offset: Offset(0.0, 0.0))]
),
child:ListView.builder(
controller: _scrollController,
scrollDirection: Axis.horizontal,
physics: const NeverScrollableScrollPhysics(),
itemCount: _items.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: (){
esLoadingToast('${_items[index]}');
},
child: Container(
color: Colors.primaries[index % Colors.primaries.length],
width: _itemWidth,
margin: EdgeInsets.only(right: _itemSpacing),
child: _items[index]
),
);
},
),
);
}
//内部需要滚动的具体模块布局
_promoBanner(){return Container() }
_aTuiExpBanner(){return Container() }
_productSelectionBanner(){return Container() }
}
引用(如果需要从外部传入参数渲染显示数据,需保证用到的参数不为空,因为initState()只调用一遍,而在数据请求未完成时一般早已执行了initState(),这会导致走马灯内部数据为空)
if (_recommendModel.promotionExpressList != null
&& _recommendModel.marketExpList != null
&& _recommendModel.productSelectionGoodsList.isNotEmpty)
SmoothInfiniteScroll(_recommendModel),
3107

被折叠的 条评论
为什么被折叠?



