flutter/lib/pages/index/index.dart
2025-07-21 15:46:30 +08:00

499 lines
20 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/// 首页模板
library;
import 'dart:ui';
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/IM/im_message.dart';
import 'package:loopin/components/custom_sticky_header.dart';
import '../../behavior/custom_scroll_behavior.dart';
import '../../components/backtop.dart';
import '../../components/loading.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': '评价中心'}
]
}
];
List<String> tabList = ['推荐', '美食', '娱乐', '文旅', '医疗', '房产'];
// 瀑布流列表
List waterfallData = [
{
'price': 199.00,
'title': '韩料界的萨莉亚!',
'shop': '萨莉亚专卖店',
'image': 'https://qcloud.dpfile.com/pc/1c3egbzM_ICz90dhi6MAiTsazjxWYQcHCd-sbpD1Wqtph2eIJA04NCRvoGqL4_opG45IiB1YIyNuDTtqzVRwesm_qA1Pf8rFcayTY-n-rG8.jpg',
'saleNum': '2.1万'
},
{
'price': 1499.90,
'title': '茅台MOUTAI飞天 53%vol 500ml 贵州茅台酒(带杯)',
'shop': '茅台京东自营旗舰店',
'image': 'https://img13.360buyimg.com/n1/jfs/t1/97097/12/15694/245806/5e7373e6Ec4d1b0ac/9d8c13728cc2544d.jpg',
'saleNum': '1254'
},
{
'price': 18.90,
'title': '上海街头苹果糖!一口一个不吱声',
'shop': '芝洛洛自营旗舰店',
'image': 'https://p0.meituan.net/coverpic/f0eefdfa02619fb09ca53eacd4d97231123115.jpg',
'saleNum': '1.2万'
},
{
'price': 59.00,
'title': '谁懂,就是这个菜,尝了第一口,立马决定加单了,真正的咸甜永动机啊🍬 去过云南的朋友都知道,当地的乳扇真的很好吃。',
'shop': '薄荷牛舌卷旗舰店',
'image': 'https://qcloud.dpfile.com/pc/UcW-v6AN1TxVTt9--5Kaw2-t4W55jUhEG_pM5S-w_AQ4IP3z9WxHzwJ9fOthIjEYY0q73sB2DyQcgmKUxZFQtw.jpg',
'saleNum': '1639'
},
{
'price': 2499.00,
'title': '小米 REDMI K80 国家补贴 第三代骁龙 8 6550mAh大电池 澎湃OS 玄夜黑 12GB+256GB 红米5G至尊手机',
'shop': '小米京东自营旗舰店',
'image': 'https://img10.360buyimg.com/n1/s450x450_jfs/t1/264409/38/13856/102861/678dcfdaFb723c58f/5b97cf154bbba96c.jpg',
'saleNum': '9726'
},
{
'price': 1.00,
'title': '圣菲尔伯爵法国红酒Saintfilcount干红葡萄酒珍藏13.5度单瓶送礼红酒 一元试饮',
'shop': '小森葡萄酒专营店',
'image': 'https://img10.360buyimg.com/n7/jfs/t1/226168/23/3411/118733/65537e5fF2db2d109/7d1d11a8013d6e8f.jpg',
'saleNum': '9.9万'
},
{
'price': 42.00,
'title': '美的MideaLED便携充电小台灯书桌学习阅读灯学生宿舍卧室床头灯学习台灯',
'shop': '美的Midea旗舰店',
'image': 'https://img14.360buyimg.com/mobilecms/s360x360_jfs/t1/226233/4/10194/156936/658e8f88Fcfc9cb40/cea4a48783f11a7a.jpg',
'saleNum': '5106'
},
{
'price': 22.90,
'title': '蒙都 羊杂500g 加热即食 京东超市肉干肉脯及礼包11.11真便宜',
'shop': '蒙都旗舰店',
'image': 'https://img10.360buyimg.com/n7/jfs/t1/155306/32/25324/231912/62d22fb8E4ffab855/c6001ee702fb240a.jpg',
'saleNum': '1.6万'
},
{
'price': 19.90,
'title': '『 江西炒米粉 』本次最佳😋香就一个字话。锅气的香🔥干辣椒的焦香🌶️油的润香🐷蔬菜混合的清香🥬',
'shop': '去月球野餐嗎',
'image': 'https://qcloud.dpfile.com/pc/pOAOL-DQRBWfkVZIWYVoy0mMQf6_UutNlOpEpGkT_nz3b1n7ZbpikPgtXMhMsjXNY0q73sB2DyQcgmKUxZFQtw.jpg',
'saleNum': '3.2万'
},
{
'price': 109.00,
'title': '附近新开业的,作为江西人当然要去试试。点了几个家常菜。',
'shop': '辣评新开江西菜',
'image': 'https://qcloud.dpfile.com/pc/HePD48CFNnS0kMZyf3Q391wxaW_zVgHimctthH__J6UI54HLPUkNt5e3qtP4Nl2G_aW_B6sGElzX-tSmYRvRnQxxxek7cKy7_R0W-KdxWUk.jpg',
'saleNum': '8764'
},
];
// 列表
List dataList = [];
// 是否加载中
bool isLoading = false;
late ScrollController scrollController = ScrollController();
late TabController tabController = TabController(initialIndex: 0, length: tabList.length, vsync: this);
final PageController pageController = PageController();
// 滚动位置
double scrollOffset = 0;
// 加载更多
loadMoreData() async {
setState(() {
isLoading = true;
});
await Future.delayed(Duration(seconds: 1));
setState(() {
dataList.addAll(waterfallData);
isLoading = false;
});
}
// 下拉刷新
Future<void> handleRefresh() async {
await Future.delayed(Duration(seconds: 1));
dataList.clear();
for (int i = 0; i < waterfallData.length; i++) {
dataList.add(waterfallData[i]);
}
if (mounted) {
setState(() {});
}
}
// 瀑布流卡片
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['image']}'),
Container(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 5.0,
children: [
Text(
'${item['title']}',
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['saleNum']}',
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();
scrollController.addListener(() {
setState(() {
scrollOffset = scrollController.offset;
});
if (scrollController.position.pixels == scrollController.position.maxScrollExtent) {
debugPrint('[index]滚动到底部');
if (!isLoading) {
loadMoreData();
}
}
});
// 初始化加载
handleRefresh();
}
@override
void dispose() {
scrollController.dispose();
tabController.dispose();
pageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
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: [
Image.network(
'https://m.360buyimg.com/babel/jfs/t20271217/224114/35/38178/150060/6760d559Fd654f946/968c156726b6e822.png',
fit: BoxFit.fill,
),
Image.network(
'https://m.360buyimg.com/babel/jfs/t20280117/88832/5/48468/139826/6789cbcfF4e0b2a3d/9dc54355b6f65c40.jpg',
fit: BoxFit.fill,
),
Image.network(
'https://m.360buyimg.com/babel/jfs/t20280108/255505/29/10540/137372/677ddbc1F6cdbbed0/bc477fadedef22a8.jpg',
fit: BoxFit.fill,
),
],
),
),
),
),
// 分类
// SliverToBoxAdapter(
// child: Container(
// margin: EdgeInsets.all(10.0),
// padding: EdgeInsets.symmetric(vertical: 10.0),
// height: 90.0,
// clipBehavior: Clip.antiAlias,
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(15.0),
// ),
// child: Column(
// children: [
// Expanded(
// child: PageView.builder(
// controller: pageController,
// itemCount: cateList.length,
// itemBuilder: (context, index) {
// final item = cateList[index];
// return GridView.builder(
// shrinkWrap: true,
// padding: EdgeInsets.zero,
// physics: NeverScrollableScrollPhysics(),
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 4,
// ),
// itemCount: item['list'].length,
// itemBuilder: (BuildContext context, int index) {
// final citem = item['list'][index];
// // return Column(
// // spacing: 3.0,
// // children: [
// // if (citem['icon'] != null)
// // SvgPicture.asset(
// // 'assets/images/svg/${citem['icon']}',
// // height: 30.0,
// // width: 30.0,
// // ),
// // Text(citem['label']),
// // ],
// // );
// return GestureDetector(
// onTap: () {
// logger.i('点击了$index');
// // 跳转逻辑,用你自己的目标路由替换
// Get.toNamed('/order');
// },
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// if (citem['icon'] != null)
// SvgPicture.asset(
// 'assets/images/svg/${citem['icon']}',
// height: 30.0,
// width: 30.0,
// ),
// Text(citem['label']),
// ],
// ),
// );
// },
// );
// },
// ),
// ),
// CustomPageViewIndicator(
// controller: pageController,
// count: cateList.length,
// color: Color(0xFFCECECE),
// activeColor: Color(0xFFFF5000),
// ),
// ],
// )),
// ),
// tabbar列表
SliverPersistentHeader(
pinned: true,
delegate: CustomStickyHeader(
child: PreferredSize(
preferredSize: Size.fromHeight(45.0),
child: Container(
color: Colors.white,
height: 45.0,
child: TabBar(
controller: tabController,
onTap: (index) {
logger.i('点击了第 $index 个 tab');
},
tabs: tabList.map((v) => Tab(text: v)).toList(),
isScrollable: false,
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: [
dataList.isEmpty
?
// 初始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: dataList.length + (isLoading ? 1 : 0),
itemBuilder: (BuildContext context, int index) {
if (index < dataList.length) {
return cardList(dataList[index]);
} else {
return SizedBox.shrink();
}
},
),
Opacity(opacity: dataList.isNotEmpty && isLoading ? 1 : 0, child: Loading(title: 'loading...')),
],
),
),
),
],
),
),
// 返回顶部
floatingActionButton: Backtop(controller: scrollController, offset: scrollOffset),
);
}
}