You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

520 lines
16 KiB

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart';
import 'package:huixiang/generated/l10n.dart';
import 'package:huixiang/main.dart';
import 'package:huixiang/retrofit/data/banner.dart';
import 'package:huixiang/retrofit/data/base_data.dart';
import 'package:huixiang/retrofit/data/brand_data.dart';
import 'package:huixiang/retrofit/retrofit_api.dart';
import 'package:huixiang/utils/event_type.dart';
import 'package:huixiang/view_widget/classic_header.dart';
import 'package:huixiang/view_widget/custom_image.dart';
import 'package:huixiang/view_widget/icon_text.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:huixiang/view_widget/loading_view.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:shared_preferences/shared_preferences.dart';
class BrandPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _BrandPage();
}
}
class _BrandPage extends State<BrandPage>
with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
ScrollController tabController;
Map<String, String> images = {
S.current.bainianchuanjiao: "assets/image/icon_chili.png",
S.current.haixiajiemei: "assets/image/icon_milk_tea.png",
S.current.qianjinmaiwei: "assets/image/icon_bread.png",
};
GlobalKey chiliGlobalKey = GlobalKey();
GlobalKey milkTeaGlobalKey = GlobalKey();
GlobalKey breadGlobalKey = GlobalKey();
ApiService apiService;
BrandData brandData;
List<BannerData> bannerData = [];
queryHome() async {
showCupertinoDialog(
context: context,
barrierDismissible: true,
builder: (context) {
return LoadingView();
});
BaseData baseData = await apiService.queryHome().catchError((error) {
refreshController.refreshFailed();
});
BaseData banner = await apiService.queryBanner({
"model": {"type": "BRAND_APP"},
}).catchError((error) {
refreshController.refreshFailed();
});
bannerData.clear();
bannerData.addAll((banner.data["records"] as List<dynamic>)
.map((e) => BannerData.fromJson(e))
.toList());
if (Navigator.canPop(context)) Navigator.of(context).pop();
if (baseData != null && baseData.isSuccess) {
refreshController.refreshCompleted();
brandData = BrandData.fromJson(baseData.data);
setState(() {});
} else {
refreshController.refreshFailed();
}
}
@override
void initState() {
super.initState();
SharedPreferences.getInstance().then((value) => {
apiService = ApiService(Dio(),
context: context, token: value.getString('token')),
queryHome(),
});
if (tabController == null) tabController = ScrollController();
tabController.addListener(() {
RenderBox chiliRenderBox =
chiliGlobalKey.currentContext.findRenderObject();
RenderBox milkTeaRenderBox =
milkTeaGlobalKey.currentContext.findRenderObject();
RenderBox breadRenderBox =
breadGlobalKey.currentContext.findRenderObject();
Offset chiliOffset = chiliRenderBox.localToGlobal(Offset.zero);
Offset milkTeaOffset = milkTeaRenderBox.localToGlobal(Offset.zero);
Offset breadOffset = breadRenderBox.localToGlobal(Offset.zero);
var top = 96.h;
if (chiliOffset.dy <= top) {
if (!isVisible) {
isVisible = true;
setState(() {});
}
} else {
var b = isVisible;
isVisible = false;
if (b) setState(() {});
selectedIndex = "";
}
if (chiliOffset.dy <= top && breadOffset.dy > top) {
selectedIndex =
(brandData.contents as Map<String, dynamic>).keys.elementAt(0);
if (selectedIndex1 != selectedIndex) {
setState(() {
print("object:$selectedIndex");
});
selectedIndex1 = selectedIndex;
}
} else if (breadOffset.dy <= top && milkTeaOffset.dy > top) {
selectedIndex =
(brandData.contents as Map<String, dynamic>).keys.elementAt(1);
if (selectedIndex1 != selectedIndex) {
setState(() {
print("object:$selectedIndex");
});
selectedIndex1 = selectedIndex;
}
} else if (milkTeaOffset.dy <= top) {
selectedIndex =
(brandData.contents as Map<String, dynamic>).keys.elementAt(2);
if (selectedIndex1 != selectedIndex) {
setState(() {
print("object:$selectedIndex");
});
selectedIndex1 = selectedIndex;
}
}
});
eventBus.on<EventType>().listen((event) {
print("object: BrandPage");
setState(() {});
});
}
String selectedIndex = "";
String selectedIndex1 = "";
RefreshController refreshController = RefreshController();
@override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
appBar: AppBar(
toolbarHeight: 40 - MediaQuery.of(context).padding.top,
backgroundColor: Colors.white,
elevation: 0,
),
body: Container(
padding: EdgeInsets.only(bottom: 76.h),
child: Stack(
children: [
Container(
child: SmartRefresher(
controller: refreshController,
enablePullDown: true,
enablePullUp: false,
header: MyHeader(),
physics: BouncingScrollPhysics(),
onRefresh: queryHome,
scrollController: tabController,
child: Container(
child: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Container(
color: Color(0xFFF7F7F7),
margin: EdgeInsets.only(top: 16),
child: Column(
children: homeChildItem(),
),
),
),
),
),
),
Positioned(
child: Visibility(
visible: isVisible,
child: Container(
width: MediaQuery.of(context).size.width,
child: Container(
height: 52.h,
color: Colors.white,
padding: EdgeInsets.all(6),
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children:
(brandData == null || brandData.contents == null)
? []
: (brandData.contents as Map<String, dynamic>)
.keys
.map((e) => item(e, selectedIndex == e))
.toList(),
),
),
),
),
top: 0,
),
],
),
),
);
}
List<Widget> homeChildItem() {
var widgets = <Widget>[banner(), buildInfo(), buildTab()];
if (brandData == null) return widgets;
(brandData.contents as Map<String, dynamic>).forEach((key, value) {
widgets.add(Container(
key: key == "百年川椒"
? chiliGlobalKey
: (key == "前进麦味" ? breadGlobalKey : milkTeaGlobalKey),
child: Container(
child: Html(
data: value,
),
),
));
});
return widgets;
}
bool isVisible = false;
Widget buildTab() {
return Container(
// key: tabGlobalKey,
height: 52.h,
padding: EdgeInsets.all(6),
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: (brandData == null || brandData.contents == null)
? []
: (brandData.contents as Map<String, dynamic>)
.keys
.map((e) => item(e, false))
.toList(),
),
);
}
Widget item(text, isSelected) {
return GestureDetector(
onTap: () {
FlexParentData parendData;
if (text == S.of(context).bainianchuanjiao) {
parendData =
chiliGlobalKey.currentContext.findRenderObject().parentData;
} else if (text == S.of(context).haixiajiemei) {
parendData =
milkTeaGlobalKey.currentContext.findRenderObject().parentData;
} else if (text == S.of(context).qianjinmaiwei) {
parendData =
breadGlobalKey.currentContext.findRenderObject().parentData;
}
double offset = parendData.offset.dy - 52.h + 20;
tabController.animateTo(offset,
duration: Duration(seconds: 1), curve: Curves.ease);
},
child: tabItem(text, selectedIndex == text),
);
}
Widget tabItem(text, isSelected) {
if (isSelected) {
return IconText(
text,
isMax: false,
rightImage: images[text],
iconSize: 16,
iconColor: Colors.red,
textStyle: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: Color(0xFF353535)),
);
} else {
return IconText(
text,
isMax: false,
textStyle: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: Color(0xFF353535)),
);
}
}
Widget buildInfo() {
return Container(
margin: EdgeInsets.only(bottom: 20, top: 16),
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(12),
offset: Offset(0, 2),
blurRadius: 14,
spreadRadius: 0,
)
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
ClipOval(
child: MImage(
brandData == null ? "" : brandData.originAvatar,
fit: BoxFit.cover,
width: 60,
height: 60,
errorSrc: "assets/image/default_1.png",
fadeSrc: "assets/image/default_1.png",
),
clipBehavior: Clip.hardEdge,
),
SizedBox(
width: 16,
),
Expanded(
child: Container(
height: 60,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text.rich(
TextSpan(children: [
TextSpan(
text: brandData == null ? "" : brandData.originator,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Colors.black,
),
),
TextSpan(
text: " 集团创办人",
style: TextStyle(
fontSize: 10,
color: Colors.black,
),
),
]),
textDirection: TextDirection.ltr,
),
Text(
brandData == null ? "" : brandData.originDesc,
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF353535),
),
),
],
),
),
flex: 1,
)
],
),
SizedBox(
height: 40,
),
Text(
brandData == null ? "" : brandData.company,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
SizedBox(
height: 20,
),
Text(
brandData == null ? "" : brandData.companyDesc,
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF353535),
),
),
SizedBox(
height: 40,
),
Text(
S.of(context).linian,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: buildIdea(),
),
],
),
);
}
List<Widget> buildIdea() {
if (brandData == null) return [];
var ideas = <Widget>[];
(brandData.ideals as Map<String, dynamic>).forEach((key, value) {
ideas.add(idea(key, value));
});
return ideas;
}
banner() {
return Container(
child: AspectRatio(
aspectRatio: 2.08,
child: Swiper(
viewportFraction: 0.88,
scale: 0.93,
// loop: true,
// autoplay: true,
// duration: 2500,
pagination: SwiperPagination(
alignment: Alignment.bottomCenter,
builder: DotSwiperPaginationBuilder(
size: 8,
activeSize: 8,
space: 5,
activeColor: Colors.black,
color: Colors.black.withAlpha(76),
),
),
physics: BouncingScrollPhysics(),
itemBuilder: (context, position) {
return MImage(
(bannerData != null && position < bannerData.length)
? bannerData[position].imgUrl
: "",
fit: BoxFit.cover,
radius: BorderRadius.circular(8),
errorSrc: "assets/image/default_2_1.png",
fadeSrc: "assets/image/default_2_1.png",
);
},
itemCount: (bannerData != null && bannerData.length > 0)
? bannerData.length
: 1),
),
);
}
Widget idea(key, value) {
return Stack(
children: [
MImage(
value,
width: 71,
height: 71,
fit: BoxFit.cover,
errorSrc: "assets/image/default_1.png",
fadeSrc: "assets/image/default_1.png",
),
Positioned(
bottom: 0,
child: Container(
width: 71,
decoration: BoxDecoration(
color: Colors.black.withAlpha(125),
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(4),
bottomLeft: Radius.circular(4),
),
),
padding: EdgeInsets.symmetric(vertical: 2),
alignment: Alignment.center,
child: Text(
key,
style: TextStyle(
color: Colors.white,
fontSize: 12.sp,
),
),
),
)
],
);
}
@override
bool get wantKeepAlive => true;
}