499 lines
20 KiB
Dart
499 lines
20 KiB
Dart
/// 首页模板
|
||
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': '美的(Midea)LED便携充电小台灯书桌学习阅读灯学生宿舍卧室床头灯学习台灯',
|
||
'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),
|
||
);
|
||
}
|
||
}
|