flutter/lib/pages/index/indexcopy.dart
2025-09-17 15:32:18 +08:00

496 lines
20 KiB
Dart

/// 首页模板
library;
import 'package:card_swiper/card_swiper.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:get/get.dart';
import 'package:loopin/behavior/custom_scroll_behavior.dart';
import 'package:loopin/components/backtop.dart';
import 'package:loopin/components/custom_sticky_header.dart';
import 'package:loopin/components/loading.dart';
import 'package:loopin/components/only_down_scroll_physics.dart';
import 'package:loopin/controller/shop_index_controller.dart';
class IndexPage extends StatefulWidget {
const IndexPage({super.key});
@override
State<IndexPage> createState() => _IndexPageState();
}
class _IndexPageState extends State<IndexPage> with SingleTickerProviderStateMixin {
// 分类列表
// List cateList = [
// {
// 'id': 1,
// 'list': [
// {
// 'icon': 'order.svg',
// 'label': '我的订单',
// },
// {
// 'icon': 'chongzhi.svg',
// 'label': '充值中心',
// },
// {'icon': 'qianbao.svg', 'label': '余额'},
// {'icon': 'comment.svg', 'label': '评价中心'}
// ]
// }
// ];
final ScrollController pageScrollController = ScrollController();
final ShopIndexController controller = Get.put(ShopIndexController());
// 下拉刷新初始化
Future<void> handleRefresh() async {}
///商品详情
void shopDetail() async {
// final res = await Http.get('${ShopApi.shopDetail}/1938137499482869762');
// logger.e(res['data']);
}
// 瀑布流卡片
Widget cardList(item) {
return GestureDetector(
child: Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(5),
offset: Offset(0.0, 1.0),
blurRadius: 1.0,
spreadRadius: 0.0,
),
]),
child: Column(
children: [
Image.network('${item['pic']}'),
Container(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 5.0,
children: [
Text(
'${item['name']}',
style: TextStyle(fontSize: 14.0, height: 1.2),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
Row(
spacing: 5.0,
children: [
Text.rich(
TextSpan(style: TextStyle(color: Colors.red, fontSize: 12.0, fontWeight: FontWeight.w700, fontFamily: 'Arial'), children: [
TextSpan(text: '¥'),
TextSpan(
text: '${item['price']}',
style: TextStyle(
fontSize: 16.0,
)),
]),
),
Text(
'已售${item['sales']}',
style: TextStyle(color: Colors.grey, fontSize: 10.0),
),
],
),
Text(
'${item['shop']}',
style: TextStyle(color: Colors.grey, fontSize: 12.0),
),
],
),
)
],
),
),
onTap: () {
Get.toNamed('/goods');
},
);
}
@override
void initState() {
super.initState();
// controller.initTabs(vsync: this);
}
@override
Widget build(BuildContext context) {
return Obx(() {
final tabIndex = controller.currentTabIndex.value;
final scrollController = controller.tabs[tabIndex]?.scrollController;
final pagesView = controller.tabs[tabIndex];
return Scaffold(
backgroundColor: Colors.grey[50],
body: ScrollConfiguration(
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
child: CustomScrollView(
scrollBehavior: CustomScrollBehavior().copyWith(scrollbars: false),
controller: scrollController,
slivers: [
SliverAppBar(
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
pinned: true,
expandedHeight: 200.0,
titleSpacing: 10.0,
// 搜索框(高斯模糊背景)
// title: ClipRRect(
// borderRadius: BorderRadius.circular(30.0),
// child: BackdropFilter(
// filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
// child: Container(
// height: 45.0,
// decoration: BoxDecoration(
// color: Colors.white.withAlpha(200),
// ),
// child: TextField(
// decoration: InputDecoration(
// isDense: true,
// hintText: "2025百亿补贴",
// hintStyle: TextStyle(fontSize: 15.0),
// prefixIcon: Icon(
// Icons.search,
// color: Colors.black38,
// size: 21.0,
// ),
// suffixIcon: Container(
// padding: EdgeInsets.only(right: 15.0),
// child: Row(
// mainAxisSize: MainAxisSize.min,
// spacing: 10.0,
// children: [
// Icon(
// Icons.keyboard_voice,
// color: Colors.black45,
// size: 21.0,
// ),
// Icon(
// Icons.camera_alt_outlined,
// color: Colors.black45,
// size: 21.0,
// ),
// ],
// ),
// ),
// contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 10.0),
// border: OutlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(30.0))),
// cursorColor: Colors.black,
// onChanged: (val) {
// debugPrint(val);
// },
// ),
// ),
// ),
// ),
// actions: [
// IconButton(
// icon: Icon(Icons.shopping_cart_outlined),
// onPressed: () {},
// ),
// ],
// 自定义伸缩区域(轮播图)
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFFFF5000), Color(0xFFfcaec4)])),
child: FlexibleSpaceBar(
background: Swiper.children(
pagination: SwiperPagination(
builder: DotSwiperPaginationBuilder(
color: Colors.white70,
activeColor: Colors.white,
),
),
indicatorLayout: PageIndicatorLayout.SCALE,
children: [
...controller.swiperData.map((item) {
final imageUrl = item['images'] ?? '';
return imageUrl.isNotEmpty
? Image.network(
imageUrl,
fit: BoxFit.fill,
)
: SizedBox.shrink();
}),
],
),
),
),
),
// tabbar列表
SliverPersistentHeader(
pinned: true,
delegate: CustomStickyHeader(
child: PreferredSize(
preferredSize: Size.fromHeight(45.0),
child: Container(
color: Colors.white,
height: 45.0,
child: TabBar(
controller: controller.tabController,
onTap: (index) {
print('点击了第 $index 个 tab');
},
tabs: controller.tabList.map((v) => Tab(text: v['name'])).toList(),
isScrollable: true,
overlayColor: WidgetStateProperty.all(Colors.transparent),
unselectedLabelColor: Colors.black87,
labelColor: Color(0xFFFF5000),
indicatorColor: Color(0xFFFF5000),
indicatorSize: TabBarIndicatorSize.tab,
unselectedLabelStyle: TextStyle(fontSize: 15.0, fontFamily: 'Microsoft YaHei'),
labelStyle: TextStyle(fontSize: 15.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.w700),
dividerHeight: 0,
padding: EdgeInsets.symmetric(horizontal: 10.0),
labelPadding: EdgeInsets.symmetric(horizontal: 7.5),
indicatorPadding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 5.0),
),
),
),
),
),
// 瀑布流列表
SliverToBoxAdapter(
child: Container(
padding: EdgeInsets.all(10.0),
child: Column(
children: [
pagesView?.dataList.isEmpty ?? true
?
// 初始loading提示
Column(
children: [
RefreshProgressIndicator(
backgroundColor: Colors.white,
color: Color(0xFFFF5000),
),
],
)
: MasonryGridView.count(
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: NeverScrollableScrollPhysics(),
crossAxisCount: 2,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
itemCount: ((pagesView?.dataList.length ?? 0) + (pagesView?.isLoading.value == true ? 1 : 0)),
itemBuilder: (BuildContext context, int index) {
final dataList = pagesView?.dataList ?? [];
if (index < dataList.length) {
return cardList(dataList[index]);
} else {
return SizedBox.shrink();
}
},
),
Opacity(
opacity: ((pagesView?.dataList.isNotEmpty ?? false) && (pagesView?.isLoading.value ?? false)) ? 1 : 0,
child: Loading(title: 'loading...'),
),
],
),
),
),
],
),
),
// 返回顶部
floatingActionButton: pagesView != null
? Backtop(
controller: pagesView.scrollController,
offset: pagesView.scrollOffset.value,
)
: null,
);
});
}
// @override
// Widget build(BuildContext context) {
// return Obx(() {
// final tabIndex = controller.currentTabIndex.value;
// final pagesView = controller.tabs[tabIndex];
// return Scaffold(
// backgroundColor: Colors.grey[50],
// body: NestedScrollViewPlus(
// // controller: pageScrollController,
// overscrollBehavior: OverscrollBehavior.outer,
// physics: (pagesView!.dataList.length > 4 && pagesView.currentPage > 1)
// ? const OnlyDownScrollPhysics(parent: AlwaysScrollableScrollPhysics())
// : const AlwaysScrollableScrollPhysics(),
// headerSliverBuilder: (context, innerBoxIsScrolled) {
// return [
// SliverAppBar(
// backgroundColor: Colors.transparent,
// foregroundColor: Colors.white,
// pinned: true,
// stretch: false,
// onStretchTrigger: () async {
// print('触发 stretch 拉伸');
// // 加载刷新逻辑
// },
// expandedHeight: 180.0,
// // collapsedHeight: kToolbarHeight,
// collapsedHeight: 180.0,
// // 自定义伸缩区域(轮播图)
// flexibleSpace: Container(
// decoration: BoxDecoration(
// gradient: LinearGradient(
// begin: Alignment.topLeft,
// end: Alignment.bottomRight,
// colors: [
// Color(0xFFFF5000),
// Color(0xFFfcaec4),
// ],
// ),
// ),
// child: FlexibleSpaceBar(
// background: Swiper.children(
// pagination: SwiperPagination(
// builder: DotSwiperPaginationBuilder(
// color: Colors.white70,
// activeColor: Colors.white,
// ),
// ),
// indicatorLayout: PageIndicatorLayout.SCALE,
// children: [
// ...controller.swiperData.map((item) {
// final imageUrl = item['images'] ?? '';
// return imageUrl.isNotEmpty
// ? Image.network(
// imageUrl,
// fit: BoxFit.fill,
// )
// : SizedBox.shrink();
// }),
// ],
// ),
// ),
// ),
// ),
// // tab吸顶
// SliverPersistentHeader(
// pinned: true,
// delegate: CustomStickyHeader(
// child: PreferredSize(
// preferredSize: const Size.fromHeight(48.0),
// child: Container(
// color: Colors.white,
// child: TabBar(
// controller: controller.tabController,
// tabs: controller.tabList.map((item) {
// return Tab(
// child: Text(item['name'], style: TextStyle(fontWeight: FontWeight.bold)),
// );
// }).toList(),
// isScrollable: false,
// overlayColor: WidgetStateProperty.all(Colors.transparent),
// unselectedLabelColor: Colors.black87,
// labelColor: const Color(0xFFFF5000),
// indicator: const UnderlineTabIndicator(borderSide: BorderSide(color: Color(0xFFFF5000), width: 2.0)),
// indicatorSize: TabBarIndicatorSize.tab,
// unselectedLabelStyle: const TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei'),
// labelStyle: const TextStyle(fontSize: 18.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.bold),
// dividerHeight: 0,
// padding: const EdgeInsets.symmetric(horizontal: 10.0),
// labelPadding: const EdgeInsets.symmetric(horizontal: 15.0),
// ),
// ),
// ),
// ),
// ),
// ];
// },
// body: TabBarView(
// controller: controller.tabController,
// children: controller.tabList.map((tabItem) {
// final index = controller.tabList.indexOf(tabItem);
// return buildTabContent(index);
// }).toList(),
// ),
// ),
// );
// });
// }
//子view
Widget buildTabContent(int index) {
final tabState = controller.tabs[index]!;
return Obx(() {
if (tabState.dataList.isEmpty && tabState.isLoading.value) {
return const Center(
child: RefreshProgressIndicator(
backgroundColor: Colors.white,
color: Color(0xFFFF5000),
),
);
}
return CustomScrollView(
primary: false,
controller: tabState.scrollController,
slivers: [
SliverPadding(
padding: const EdgeInsets.all(10.0),
sliver: SliverMasonryGrid.count(
crossAxisCount: 2,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childCount: tabState.dataList.length,
itemBuilder: (context, idx) => cardList(tabState.dataList[idx]),
),
),
SliverFillRemaining(
hasScrollBody: false,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: Center(
child: tabState.isLoading.value ? const Loading(title: 'loading...') : const Text('没有更多数据了'),
),
),
),
],
);
});
}
//
// 空状态提示
Widget emptyTip(String text) {
return CustomScrollView(
physics: const OnlyDownScrollPhysics(),
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.only(top: 50.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset('assets/images/empty.png', width: 100.0),
const SizedBox(height: 8.0),
Text(
text,
style: const TextStyle(color: Colors.grey, fontSize: 13.0),
),
],
),
),
),
),
],
);
}
}