|
|
|
@ -1,6 +1,6 @@ |
|
|
|
import 'package:easy_refresh/easy_refresh.dart'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
|
|
|
import 'package:dating_touchme_app/controller/home/home_controller.dart'; |
|
|
|
import 'package:dating_touchme_app/model/home/marriage_data.dart'; |
|
|
|
import 'package:dating_touchme_app/pages/home/content_card.dart'; |
|
|
|
@ -16,17 +16,17 @@ class RecommendTab extends StatefulWidget { |
|
|
|
class _RecommendTabState extends State<RecommendTab> |
|
|
|
with AutomaticKeepAliveClientMixin { |
|
|
|
final HomeController controller = Get.find<HomeController>(); |
|
|
|
late final RefreshController _refreshController; |
|
|
|
// late final RefreshController _refreshController; |
|
|
|
|
|
|
|
@override |
|
|
|
void initState() { |
|
|
|
super.initState(); |
|
|
|
_refreshController = RefreshController(initialRefresh: false); |
|
|
|
// _refreshController = RefreshController(initialRefresh: false); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
void dispose() { |
|
|
|
_refreshController.dispose(); |
|
|
|
// _refreshController.dispose(); |
|
|
|
super.dispose(); |
|
|
|
} |
|
|
|
|
|
|
|
@ -37,118 +37,127 @@ class _RecommendTabState extends State<RecommendTab> |
|
|
|
final bottomPadding = MediaQuery.of(context).padding.bottom; |
|
|
|
final tabBarHeight = 64.0; |
|
|
|
final totalBottomPadding = bottomPadding + tabBarHeight; |
|
|
|
return SizedBox( |
|
|
|
height: MediaQuery.of(context).size.height - totalBottomPadding, |
|
|
|
child: Obx(() { |
|
|
|
final List<MarriageData> dataSource = controller.recommendFeed; |
|
|
|
return Obx(() { |
|
|
|
// final List<MarriageData> dataSource = controller.recommendFeed; |
|
|
|
|
|
|
|
return SmartRefresher( |
|
|
|
controller: _refreshController, |
|
|
|
enablePullDown: true, |
|
|
|
enablePullUp: true, |
|
|
|
physics: const ClampingScrollPhysics(), |
|
|
|
header: const ClassicHeader( |
|
|
|
refreshingText: '正在刷新...', |
|
|
|
completeText: '刷新完成', |
|
|
|
idleText: '下拉刷新', |
|
|
|
releaseText: '释放刷新', |
|
|
|
), |
|
|
|
footer: ClassicFooter( |
|
|
|
idleText: '上拉加载', |
|
|
|
loadingText: '正在加载...', |
|
|
|
noDataText: '没有更多数据', |
|
|
|
canLoadingText: '释放加载', |
|
|
|
), |
|
|
|
// 下拉刷新 |
|
|
|
onRefresh: () async { |
|
|
|
print('推荐列表下拉刷新被触发'); |
|
|
|
return EasyRefresh( |
|
|
|
controller: EasyRefreshController(), |
|
|
|
header: const ClassicHeader( |
|
|
|
dragText: '下拉刷新', |
|
|
|
armedText: '释放刷新', |
|
|
|
readyText: '刷新中...', |
|
|
|
processingText: '刷新中...', |
|
|
|
processedText: '刷新完成', |
|
|
|
failedText: '刷新失败', |
|
|
|
noMoreText: '没有更多数据', |
|
|
|
showMessage: false |
|
|
|
), |
|
|
|
footer: ClassicFooter( |
|
|
|
dragText: '上拉加载', |
|
|
|
armedText: '释放加载', |
|
|
|
readyText: '加载中...', |
|
|
|
processingText: '加载中...', |
|
|
|
processedText: '加载完成', |
|
|
|
failedText: '加载失败', |
|
|
|
noMoreText: '没有更多数据', |
|
|
|
showMessage: false |
|
|
|
), |
|
|
|
// 下拉刷新 |
|
|
|
onRefresh: () async { |
|
|
|
print('推荐列表下拉刷新被触发'); |
|
|
|
try { |
|
|
|
await controller.refreshRecommendData(); |
|
|
|
print( |
|
|
|
'推荐列表刷新完成, hasMore: $controller.recommendHasMore.value'); |
|
|
|
|
|
|
|
// _refreshController.loadComplete(); |
|
|
|
} catch (e) { |
|
|
|
print('推荐列表刷新失败: $e'); |
|
|
|
// _refreshController.refreshFailed(); |
|
|
|
} |
|
|
|
}, |
|
|
|
// 上拉加载更多 |
|
|
|
onLoad: () async { |
|
|
|
print( |
|
|
|
'推荐列表上拉加载被触发, hasMore: $controller.recommendHasMore.value'); |
|
|
|
if (controller.recommendHasMore.value) { |
|
|
|
try { |
|
|
|
await controller.refreshRecommendData(); |
|
|
|
print('推荐列表刷新完成, hasMore: $controller.recommendHasMore.value'); |
|
|
|
_refreshController.refreshCompleted(); |
|
|
|
_refreshController.loadComplete(); |
|
|
|
} catch (e) { |
|
|
|
print('推荐列表刷新失败: $e'); |
|
|
|
_refreshController.refreshFailed(); |
|
|
|
} |
|
|
|
}, |
|
|
|
// 上拉加载更多 |
|
|
|
onLoading: () async { |
|
|
|
print('推荐列表上拉加载被触发, hasMore: $controller.recommendHasMore.value'); |
|
|
|
if (controller.recommendHasMore.value) { |
|
|
|
try { |
|
|
|
await controller.loadRecommendMoreData(); |
|
|
|
// 完成加载,根据是否有更多数据决定 |
|
|
|
if (controller.recommendHasMore.value) { |
|
|
|
_refreshController.loadComplete(); |
|
|
|
print('推荐列表加载更多成功'); |
|
|
|
} else { |
|
|
|
_refreshController.loadNoData(); |
|
|
|
print('推荐列表没有更多数据了'); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
print('推荐列表加载更多失败: $e'); |
|
|
|
_refreshController.loadFailed(); |
|
|
|
await controller.loadRecommendMoreData(); |
|
|
|
// 完成加载,根据是否有更多数据决定 |
|
|
|
if (controller.recommendHasMore.value) { |
|
|
|
// _refreshController.loadComplete(); |
|
|
|
print('推荐列表加载更多成功'); |
|
|
|
} else { |
|
|
|
// _refreshController.loadNoData(); |
|
|
|
print('推荐列表没有更多数据了'); |
|
|
|
} |
|
|
|
} else { |
|
|
|
_refreshController.loadNoData(); |
|
|
|
print('推荐列表没有更多数据'); |
|
|
|
} catch (e) { |
|
|
|
print('推荐列表加载更多失败: $e'); |
|
|
|
// _refreshController.loadFailed(); |
|
|
|
} |
|
|
|
}, |
|
|
|
child: ListView.separated( |
|
|
|
// 关键:始终允许滚动,即使内容不足 |
|
|
|
physics: AlwaysScrollableScrollPhysics(), // 保持一致的滚动物理 |
|
|
|
// 移除顶部 padding,让刷新指示器可以正确显示在 AppBar 下方 |
|
|
|
padding: EdgeInsets.only( |
|
|
|
left: 12, |
|
|
|
right: 12, |
|
|
|
bottom: 12, |
|
|
|
), |
|
|
|
itemBuilder: (context, index) { |
|
|
|
// 空数据状态 |
|
|
|
if (dataSource.isEmpty && index == 0) { |
|
|
|
// 使用足够的高度确保可以滚动 |
|
|
|
if(controller.recommendIsLoading.value){ |
|
|
|
return SizedBox( |
|
|
|
height: MediaQuery.of(context).size.height - totalBottomPadding, |
|
|
|
child: Center( |
|
|
|
child: Column( |
|
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
|
children: [ |
|
|
|
CircularProgressIndicator(), |
|
|
|
SizedBox(height: 16), |
|
|
|
Text('加载数据中...'), |
|
|
|
], |
|
|
|
), |
|
|
|
} else { |
|
|
|
// _refreshController.loadNoData(); |
|
|
|
print('推荐列表没有更多数据'); |
|
|
|
} |
|
|
|
}, |
|
|
|
child: SizedBox( |
|
|
|
height: MediaQuery.of(context).size.height - totalBottomPadding, |
|
|
|
child: ListView.separated( |
|
|
|
// 关键:始终允许滚动,即使内容不足 |
|
|
|
// 移除顶部 padding,让刷新指示器可以正确显示在 AppBar 下方 |
|
|
|
padding: EdgeInsets.only( |
|
|
|
left: 12, |
|
|
|
right: 12, |
|
|
|
bottom: 12, |
|
|
|
), |
|
|
|
itemBuilder: (context, index) { |
|
|
|
// 空数据状态 |
|
|
|
if (controller.recommendFeed.isEmpty && index == 0) { |
|
|
|
// 使用足够的高度确保可以滚动 |
|
|
|
if (controller.recommendIsLoading.value) { |
|
|
|
return SizedBox( |
|
|
|
height: MediaQuery.of(context).size.height - totalBottomPadding, |
|
|
|
child: Center( |
|
|
|
child: Column( |
|
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
|
children: [ |
|
|
|
CircularProgressIndicator(), |
|
|
|
SizedBox(height: 16), |
|
|
|
Text('加载数据中...'), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
} else { |
|
|
|
return SizedBox( |
|
|
|
height: MediaQuery.of(context).size.height - totalBottomPadding, |
|
|
|
child: const Center( |
|
|
|
child: Text( |
|
|
|
"暂无数据", |
|
|
|
style: TextStyle(fontSize: 14, color: Color(0xFF999999)), |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} else { |
|
|
|
return SizedBox( |
|
|
|
height: MediaQuery |
|
|
|
.of(context) |
|
|
|
.size |
|
|
|
.height - totalBottomPadding, |
|
|
|
child: const Center( |
|
|
|
child: Text( |
|
|
|
"暂无数据", |
|
|
|
style: TextStyle(fontSize: 14, color: Color(0xFF999999)), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
// 数据项 |
|
|
|
final item = dataSource[index]; |
|
|
|
return ContentCard(item: item); |
|
|
|
}, |
|
|
|
separatorBuilder: (context, index) { |
|
|
|
// 空状态或加载状态时不显示分隔符 |
|
|
|
if (dataSource.isEmpty) return const SizedBox.shrink(); |
|
|
|
return const SizedBox(height: 12); |
|
|
|
}, |
|
|
|
// 至少显示一个 item(用于显示加载或空状态) |
|
|
|
itemCount: dataSource.isEmpty ? 1 : dataSource.length, |
|
|
|
} |
|
|
|
// 数据项 |
|
|
|
final item = controller.recommendFeed[index]; |
|
|
|
return ContentCard(item: item); |
|
|
|
}, |
|
|
|
separatorBuilder: (context, index) { |
|
|
|
// 空状态或加载状态时不显示分隔符 |
|
|
|
if (controller.recommendFeed.isEmpty) return const SizedBox.shrink(); |
|
|
|
return const SizedBox(height: 12); |
|
|
|
}, |
|
|
|
// 至少显示一个 item(用于显示加载或空状态) |
|
|
|
itemCount: controller.recommendFeed.isEmpty ? 1 : controller.recommendFeed.length, |
|
|
|
) |
|
|
|
), |
|
|
|
); |
|
|
|
}), |
|
|
|
); |
|
|
|
); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
|