home.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:provider/provider.dart';
  4. import 'package:flutter_swiper/flutter_swiper.dart';
  5. import 'package:flutter_easyrefresh/easy_refresh.dart';
  6. import 'package:color_thief_flutter/color_thief_flutter.dart';
  7. import 'package:cached_network_image/cached_network_image.dart';
  8. import 'package:twong/api/index.dart';
  9. import 'package:twong/pages/tabs.dart';
  10. import 'package:twong/utils/index.dart';
  11. import 'package:twong/router/index.dart';
  12. import 'package:twong/config/style.dart';
  13. import 'package:twong/models/index.dart';
  14. import 'package:twong/widgets/fsuper.dart';
  15. import 'package:twong/providers/home.dart';
  16. import 'package:twong/providers/message.dart';
  17. import 'package:twong/utils/image_utils.dart';
  18. import 'package:twong/widgets/search_bar.dart';
  19. import 'package:twong/widgets/sliver_bar.dart';
  20. import 'package:twong/widgets/product_item.dart';
  21. class HomePage extends StatefulWidget {
  22. @override
  23. State<StatefulWidget> createState() {
  24. return _HomePageState();
  25. }
  26. }
  27. class _HomePageState extends State<HomePage> {
  28. Home _data;
  29. int _currentPage = 1;
  30. bool _checkColor = true;
  31. Color headerColor = Colors.red;
  32. ScrollController _controller = ScrollController();
  33. @override
  34. initState() {
  35. super.initState();
  36. loadData();
  37. _controller.addListener(_onScroll);
  38. }
  39. loadData() async {
  40. _data = Cache.get(SaveKey.home);
  41. if(Cache.user == null) {
  42. Network.inst.autoLogin().then((res) {
  43. getData();
  44. });
  45. } else {
  46. getData();
  47. }
  48. }
  49. getData() {
  50. Network.inst.getIndex().then((res) {
  51. setState(() {
  52. _data = Provider
  53. .of<HomeModel>(context, listen: false)
  54. .data;
  55. headerColor = Provider
  56. .of<HomeModel>(context, listen: false)
  57. .headerColor;
  58. });
  59. Cache.set(SaveKey.home, _data);
  60. });
  61. }
  62. _onSwipeChange(int index) async {
  63. if (!_checkColor) return;
  64. var image = CachedNetworkImageProvider(_data.banner[index].pic);
  65. getColorFromImage(await getImageFromProvider(image)).then((color) {
  66. var colors = Color.fromARGB(255, color[0], color[1], color[2]);
  67. var hsl = HSLColor.fromColor(colors);
  68. // 降低颜色亮度
  69. colors = hsl.withLightness(hsl.lightness * 3 / 4).toColor();
  70. setState(() {
  71. headerColor = colors;
  72. });
  73. // Provider.of<HomeModel>(context, listen: false).setHeaderColor(colors);
  74. }).catchError((err) {
  75. Log.d(err);
  76. });
  77. }
  78. Widget _buildSlider (BuildContext context, int index) {
  79. var banner = _data.banner[index];
  80. return CachedNetworkImage(
  81. fit: BoxFit.cover,
  82. imageUrl: banner.pic,
  83. imageBuilder: (BuildContext context, ImageProvider<dynamic> provider) {
  84. return GestureDetector(
  85. onTap: () {
  86. var id = banner.url.split("/")[2];
  87. Navigator.pushNamed(context, RouteNames.productDetails, arguments: id);
  88. },
  89. child: Container(
  90. decoration: BoxDecoration(
  91. borderRadius: BorderRadius.circular(4.px),
  92. image: DecorationImage(
  93. image: provider,
  94. fit: BoxFit.cover
  95. ),
  96. ),
  97. ),
  98. );
  99. },
  100. placeholder: (BuildContext context, String str) {
  101. return Center(child: Utils.loadingWidget);
  102. },
  103. );
  104. }
  105. Widget _buildCate () {
  106. var buildBox = (String uri) {
  107. if (uri == null) {
  108. return Container(
  109. margin: EdgeInsets.all(4),
  110. decoration: BoxDecoration(
  111. color: Colors.white,
  112. borderRadius: BorderRadius.circular(3),
  113. ),
  114. );
  115. }
  116. return InkWell(
  117. onTap: () {},
  118. child: Container(
  119. margin: EdgeInsets.all(4),
  120. decoration: BoxDecoration(
  121. borderRadius: BorderRadius.circular(3),
  122. image: DecorationImage(image: CachedNetworkImageProvider(uri), fit: BoxFit.cover),
  123. ),
  124. ),
  125. );
  126. };
  127. return Container(
  128. margin: EdgeInsets.only(left: 4.px, right: 4.px),
  129. child: Row(
  130. children: <Widget>[
  131. Expanded(flex: 4, child: buildBox(null)),
  132. Expanded(flex: 6, child: Column(
  133. children: <Widget>[
  134. Expanded( child: buildBox(null)),
  135. Expanded( child: buildBox(null)),
  136. ],
  137. ))
  138. ],
  139. ),
  140. );
  141. }
  142. Widget _buildNews () {
  143. return Container(
  144. height: 42.px,
  145. alignment: Alignment.center,
  146. child: Row(
  147. children: [
  148. Container(
  149. margin: EdgeInsets.only(left: 12.px, right: 12.px),
  150. child: Text("资讯"),
  151. ),
  152. VerticalDivider(indent: 12.px, endIndent: 12.px, color: Colors.grey),
  153. Expanded(child: Container(
  154. margin: EdgeInsets.only(left: 12.px),
  155. child: Swiper(
  156. autoplay: true,
  157. physics: NeverScrollableScrollPhysics(),
  158. scrollDirection: Axis.vertical,
  159. itemBuilder: _buildNewsSlider,
  160. itemCount: _data.roll.length,
  161. autoplayDisableOnInteraction: true,
  162. ),
  163. ))
  164. ],
  165. ),
  166. );
  167. }
  168. Widget _buildNewsSlider(BuildContext context, int index) {
  169. return Container(
  170. alignment: Alignment.centerLeft,
  171. child: Text(_data.roll[index]["info"]),
  172. );
  173. }
  174. Widget _buildProducts () {
  175. if (_data.info.firstList.length > 0) {
  176. return SliverList(
  177. delegate: SliverChildBuilderDelegate((context, index) =>
  178. ProductItem(_data.info.firstList[index]),
  179. childCount: _data.info.firstList.length),
  180. );
  181. } else {
  182. return SliverToBoxAdapter(
  183. child: Container(
  184. alignment: Alignment.center,
  185. child: Text("暂时没有数据"),
  186. ),
  187. );
  188. }
  189. }
  190. Widget _buildMenu() {
  191. var widgets = List<Widget>();
  192. for(var item in _data.menus) {
  193. widgets.add(Expanded(
  194. child: GestureDetector(
  195. onTap: () { Navigator.pushNamed(context, item.url); },
  196. child: Container(
  197. alignment: Alignment.center,
  198. margin: EdgeInsets.all(10.px),
  199. child: Column(
  200. mainAxisAlignment: MainAxisAlignment.center,
  201. children: [
  202. Expanded(child: Container(
  203. width: 40.px,
  204. margin: EdgeInsets.only(bottom: 4.px),
  205. decoration: BoxDecoration(
  206. image: DecorationImage(image: CachedNetworkImageProvider(item.pic), fit: BoxFit.cover),
  207. borderRadius: BorderRadius.circular(10.px),
  208. ),
  209. )),
  210. Text(item.name, style: TextStyle(fontSize: 11.px),)
  211. ],
  212. ),
  213. ))
  214. ));
  215. }
  216. widgets.add(Expanded(
  217. child: GestureDetector(
  218. onTap: () { TabsState.inst.doItemTap(3); },
  219. child: Container(
  220. alignment: Alignment.center,
  221. margin: EdgeInsets.all(10.px),
  222. child: Column(
  223. mainAxisAlignment: MainAxisAlignment.center,
  224. children: [
  225. Expanded(child: Container(
  226. width: 40.px,
  227. margin: EdgeInsets.only(bottom: 4.px),
  228. decoration: BoxDecoration(
  229. // image: DecorationImage(image: CachedNetworkImageProvider(""), fit: BoxFit.cover),
  230. borderRadius: BorderRadius.circular(10.px),
  231. ),
  232. )),
  233. Text(Cache.isVip ? "会员中心" : "用户中心", style: TextStyle(fontSize: 11.px))
  234. ],
  235. ),
  236. ))
  237. ));
  238. return SliverToBoxAdapter(
  239. child: Container(
  240. height: 80.px,
  241. color: Colors.white,
  242. margin: EdgeInsets.all(6.px),
  243. child: Row(
  244. children: widgets,
  245. ),
  246. )
  247. );
  248. }
  249. List<Widget> _buildDataList() {
  250. return <Widget>[
  251. SliverToBoxAdapter(
  252. child: Container(
  253. height: 150.px,
  254. decoration: BoxDecoration(
  255. gradient: LinearGradient(
  256. begin: Alignment.topCenter,
  257. end: Alignment.bottomCenter,
  258. colors: [headerColor, DColors.back],
  259. ),
  260. ),
  261. padding: EdgeInsets.only(left: 6.px, right: 6.px),
  262. child: Swiper(
  263. scale: 0.9,
  264. autoplay: true,
  265. duration: 600,
  266. autoplayDelay: 5600,
  267. itemBuilder: _buildSlider,
  268. itemCount: _data.banner.length,
  269. onIndexChanged: _onSwipeChange,
  270. pagination: SwiperPagination(),
  271. autoplayDisableOnInteraction: true,
  272. )
  273. )
  274. ),
  275. _buildMenu(),
  276. SliverToBoxAdapter(
  277. child: Container(
  278. height: 150.px,
  279. child: _buildCate()
  280. ),
  281. ),
  282. SliverToBoxAdapter(
  283. child: Container(
  284. height: 46.px,
  285. color: Colors.white,
  286. margin: EdgeInsets.all(6.px),
  287. child: _buildNews()
  288. ),
  289. ),
  290. SliverBar(),
  291. _buildProducts()
  292. ];
  293. }
  294. _buildNoData() {
  295. return <Widget>[
  296. SliverToBoxAdapter(
  297. child: Container(
  298. height: 300.px,
  299. child: Center(child: Utils.loadingWidget)
  300. ))
  301. ];
  302. }
  303. _buildBody() {
  304. return EasyRefresh.custom(
  305. onRefresh: _onRefresh,
  306. onLoad: _onLoad,
  307. bottomBouncing: true,
  308. scrollController: _controller,
  309. footer: BallPulseFooter(color: DColors.Main),
  310. header: BallPulseHeader(backgroundColor: headerColor, color: Colors.white),
  311. slivers: _data == null ? _buildNoData() : _buildDataList(),
  312. );
  313. }
  314. Future _onLoad() async {
  315. _currentPage ++;
  316. Log.i("home list load more... page: $_currentPage}");
  317. // return await Network.inst.getIndex().then((data){
  318. // if(!mounted) return;
  319. // // _data = data;
  320. // // setState(() {
  321. // // _data.info.firstList.addAll(data.info.firstList.toList());
  322. // // });
  323. // }).catchError((err) {});
  324. }
  325. Future _onRefresh() async {
  326. Log.i("refresh home");
  327. // return await Network.inst.getIndex().then((data){
  328. // // if(!mounted) return;
  329. // // setState(() {
  330. // // _data = data;
  331. // // });
  332. // }).catchError((err) {});
  333. }
  334. @override
  335. Widget build(BuildContext context) {
  336. return Scaffold(
  337. backgroundColor: DColors.back,
  338. appBar: SearchBar(null, color: headerColor, elevation: 0, actions: [
  339. Consumer<MessageModel>(
  340. builder: (context, message, child) {
  341. return FSuper(
  342. width: 38.px,
  343. height: double.infinity,
  344. onClick: () =>
  345. Navigator.pushNamed(context, RouteNames.message),
  346. child1: Icon(IconFonts.message, color: Colors.white),
  347. child1Alignment: Alignment.centerLeft,
  348. redPoint: message.data.length > 0,
  349. redPointText: message.data.length.toString(),
  350. redPointOffset: Offset(-6.px, 0),
  351. redPointColor: Colors.white,
  352. redPointTextStyle: TextStyle(color: Colors.red,
  353. fontSize: 10.px, fontWeight: FontWeight.bold),
  354. );
  355. },
  356. )
  357. ]),
  358. body: _buildBody(),
  359. floatingActionButton: _checkColor ? null : InkWell(
  360. onTap: () => _controller.animateTo(0, curve: Curves.ease,
  361. duration: Duration(milliseconds: 600)),
  362. child: Container(
  363. width: 32.px,
  364. height: 32.px,
  365. child: Icon(
  366. Icons.keyboard_arrow_up_sharp, color: Colors.white),
  367. decoration: BoxDecoration(
  368. color: Color.fromARGB(128, 243, 0, 0),
  369. borderRadius: BorderRadius.circular(10.px)
  370. ),
  371. ),
  372. ),
  373. );
  374. }
  375. void _onScroll() {
  376. if (_checkColor && _controller.offset > 300) {
  377. _checkColor = false;
  378. }
  379. if (!_checkColor && _controller.offset < 300) {
  380. _checkColor = true;
  381. }
  382. }
  383. }