| @@ -181,6 +181,12 @@ | |||
| "packageUri": "lib/", | |||
| "languageVersion": "2.0" | |||
| }, | |||
| { | |||
| "name": "event_bus", | |||
| "rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/event_bus-1.1.1", | |||
| "packageUri": "lib/", | |||
| "languageVersion": "2.0" | |||
| }, | |||
| { | |||
| "name": "file", | |||
| "rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/file-5.2.1", | |||
| @@ -463,6 +469,12 @@ | |||
| "packageUri": "lib/", | |||
| "languageVersion": "2.2" | |||
| }, | |||
| { | |||
| "name": "pull_to_refresh", | |||
| "rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/pull_to_refresh-1.6.1", | |||
| "packageUri": "lib/", | |||
| "languageVersion": "2.1" | |||
| }, | |||
| { | |||
| "name": "quiver", | |||
| "rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/quiver-2.0.5", | |||
| @@ -668,7 +680,7 @@ | |||
| "languageVersion": "2.1" | |||
| } | |||
| ], | |||
| "generated": "2020-09-04T06:52:20.100476Z", | |||
| "generated": "2020-09-07T03:45:53.992384Z", | |||
| "generator": "pub", | |||
| "generatorVersion": "2.7.2" | |||
| } | |||
| @@ -1,11 +1,20 @@ | |||
| import 'package:flutter/cupertino.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_base_widget/pages/main_page/main_page_bloc.dart'; | |||
| import 'package:zhiying_base_widget/pages/main_page/main_page_notifier.dart'; | |||
| import 'package:zhiying_base_widget/pages/main_page/main_page_sk.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'package:provider/provider.dart'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:pull_to_refresh/pull_to_refresh.dart'; | |||
| class MainPage extends StatefulWidget { | |||
| MainPage({Key key}) : super(key: key); | |||
| final Map<String, dynamic> data; | |||
| MainPage( | |||
| this.data, { | |||
| Key key, | |||
| }) : super(key: key); | |||
| @override | |||
| _MainPageState createState() => _MainPageState(); | |||
| @@ -18,23 +27,49 @@ class _MainPageState extends State<MainPage> { | |||
| backgroundColor: Color(0xfff9f9f9), | |||
| body: ChangeNotifierProvider( | |||
| create: (context) => MainPageNotifier(), | |||
| child: MainPageContainer(), | |||
| child: BlocProvider<MainPageBloc>( | |||
| bloc: MainPageBloc(), | |||
| child: _MainPageContainer(widget.data), | |||
| ), | |||
| ), | |||
| ); | |||
| } | |||
| } | |||
| class MainPageContainer extends StatefulWidget { | |||
| MainPageContainer({Key key}) : super(key: key); | |||
| class _MainPageContainer extends StatefulWidget { | |||
| final Map<String, dynamic> data; | |||
| _MainPageContainer(this.data, {Key key}) : super(key: key); | |||
| @override | |||
| _MainPageContainerState createState() => _MainPageContainerState(); | |||
| } | |||
| class _MainPageContainerState extends State<MainPageContainer> { | |||
| class _MainPageContainerState extends State<_MainPageContainer> { | |||
| WidgetType _type = WidgetType.normal; | |||
| bool _isEnded = false; | |||
| ScrollController _controller = ScrollController(); | |||
| MainPageBloc _bloc; | |||
| List<String> items = ["1", "2", "3", "4", "5", "6", "7", "8"]; | |||
| RefreshController _refreshController = | |||
| RefreshController(initialRefresh: false); | |||
| void _onRefresh() async { | |||
| // monitor network fetch | |||
| await Future.delayed(Duration(milliseconds: 1000)); | |||
| // if failed,use refreshFailed() | |||
| _refreshController.refreshCompleted(); | |||
| } | |||
| void _onLoading() async { | |||
| // monitor network fetch | |||
| await Future.delayed(Duration(milliseconds: 1000)); | |||
| // if failed,use loadFailed(),if no data return,use LoadNodata() | |||
| items.add((items.length + 1).toString()); | |||
| if (mounted) setState(() {}); | |||
| _refreshController.loadComplete(); | |||
| } | |||
| @override | |||
| void dispose() { | |||
| @@ -44,6 +79,7 @@ class _MainPageContainerState extends State<MainPageContainer> { | |||
| @override | |||
| void initState() { | |||
| _bloc = BlocProvider.of<MainPageBloc>(context); | |||
| _reload(); | |||
| _controller.addListener(() { | |||
| // print('${_controller.offset} ${_controller.position.maxScrollExtent}'); | |||
| @@ -65,11 +101,16 @@ class _MainPageContainerState extends State<MainPageContainer> { | |||
| setState(() { | |||
| _type = WidgetType.skeleton; | |||
| }); | |||
| Future.delayed(Duration(seconds: 3), () { | |||
| setState(() { | |||
| _type = WidgetType.normal; | |||
| }); | |||
| }); | |||
| WidgetModel model = WidgetModel.fromJson(widget.data); | |||
| if ((model?.components?.length ?? 0) > 0) { | |||
| _bloc.loadData(model.components.map((item) => item.modId).toList()); | |||
| } | |||
| // Future.delayed(Duration(seconds: 3), () { | |||
| // setState(() { | |||
| // _type = WidgetType.normal; | |||
| // }); | |||
| // }); | |||
| } | |||
| List<Widget> _createContent(BuildContext context) { | |||
| @@ -94,11 +135,47 @@ class _MainPageContainerState extends State<MainPageContainer> { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return SafeArea( | |||
| child: CustomScrollView( | |||
| controller: _controller, | |||
| slivers: _createContent(context), | |||
| ), | |||
| return StreamBuilder<List<List<Map<String, dynamic>>>>( | |||
| stream: _bloc.outData, | |||
| builder: (BuildContext context, AsyncSnapshot snapshot) { | |||
| if (snapshot.data == null) { | |||
| return MainPageSkeleton(); | |||
| } | |||
| _type = WidgetType.normal; | |||
| return SmartRefresher( | |||
| enablePullDown: true, | |||
| enablePullUp: true, | |||
| header: WaterDropHeader(), | |||
| footer: CustomFooter( | |||
| builder: (BuildContext context, LoadStatus mode) { | |||
| Widget body; | |||
| if (mode == LoadStatus.idle) { | |||
| body = Text("上拉加载"); | |||
| } else if (mode == LoadStatus.loading) { | |||
| body = CupertinoActivityIndicator(); | |||
| } else if (mode == LoadStatus.failed) { | |||
| body = Text("加载失败!点击重试!"); | |||
| } else if (mode == LoadStatus.canLoading) { | |||
| body = Text("松手,加载更多!"); | |||
| } else { | |||
| body = Text("没有更多数据了!"); | |||
| } | |||
| return Container( | |||
| height: 55.0, | |||
| child: Center(child: body), | |||
| ); | |||
| }, | |||
| ), | |||
| controller: _refreshController, | |||
| onRefresh: _onRefresh, | |||
| onLoading: _onLoading, | |||
| child: CustomScrollView( | |||
| controller: _controller, | |||
| slivers: _createContent(context), | |||
| ), | |||
| ); | |||
| }, | |||
| ); | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| import 'dart:async'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| class MainPageBloc extends BlocBase { | |||
| List<List<Map<String, dynamic>>> _mains = List(); | |||
| StreamController<List<List<Map<String, dynamic>>>> _mainController = | |||
| StreamController<List<List<Map<String, dynamic>>>>(); | |||
| Stream<List<List<Map<String, dynamic>>>> get outData => | |||
| _mainController.stream; | |||
| @override | |||
| void dispose() { | |||
| _mainController.close(); | |||
| _mainController = null; | |||
| } | |||
| void loadData(List<int> ids) { | |||
| NetUtil.request('/api/v1/mod', | |||
| method: NetMethod.POST, | |||
| params: Map<String, dynamic>.from({'ids': ids}), onSuccess: (data) { | |||
| Map<String, dynamic> datas = data; | |||
| List<List<Map<String, dynamic>>> result = List(); | |||
| for (int id in ids) { | |||
| if (datas.containsKey(id.toString())) { | |||
| result.add(List<Map<String, dynamic>>.from(datas[id.toString()])); | |||
| } else { | |||
| result.add(List<Map<String, dynamic>>()); | |||
| } | |||
| } | |||
| _mains = result; | |||
| _mainController.add(_mains); | |||
| }); | |||
| } | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| // ignore: must_be_immutable | |||
| class MainPageSkeleton extends StatelessWidget { | |||
| ScrollController _controller; | |||
| MainPageSkeleton({Key key}) : super(key: key) { | |||
| _controller = ScrollController(); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return SafeArea( | |||
| child: CustomScrollView( | |||
| controller: _controller, | |||
| slivers: _createContent(context), | |||
| ), | |||
| ); | |||
| } | |||
| List<Widget> _createContent(BuildContext context) { | |||
| List<Widget> list = List(); | |||
| list.addAll(WidgetFactory.create('index_carousel', | |||
| type: WidgetType.skeleton, | |||
| isSliver: true, | |||
| model: Map<String, dynamic>.from({'aaaaa': 'bbbb'}))); | |||
| list.addAll(WidgetFactory.create('index_recommend_list', | |||
| type: WidgetType.skeleton, isSliver: true)); | |||
| return list; | |||
| } | |||
| } | |||
| @@ -14,7 +14,7 @@ class BaseWidgetRegister { | |||
| // 注册页面 | |||
| static void registPage() { | |||
| PageFactory.regist('homePage', (model) => HomePage()); | |||
| PageFactory.regist('index', (model) => MainPage()); | |||
| PageFactory.regist('index', (model) => MainPage(model)); | |||
| } | |||
| // 注册控件 | |||
| @@ -4,54 +4,40 @@ import 'package:zhiying_base_widget/widgets/home_goods/home_goods_header.dart'; | |||
| import 'package:zhiying_base_widget/widgets/home_goods/skeleton/home_goods_header_sk.dart'; | |||
| import 'package:zhiying_base_widget/widgets/home_goods/skeleton/home_goods_sk.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'package:event_bus/event_bus.dart'; | |||
| class GoodsListCreater extends WidgetCreater { | |||
| @override | |||
| List<Widget> createWidgets(Map<String, dynamic> model) { | |||
| TabController controller = | |||
| TabController(initialIndex: 0, length: 6, vsync: ScrollableState()); | |||
| EventBus eventBus = EventBus(); | |||
| return [ | |||
| _createHeader(controller), | |||
| _createBody(controller), | |||
| SliverPersistentHeader( | |||
| pinned: true, | |||
| floating: false, | |||
| delegate: HomeGoodsDelegate(), | |||
| ), | |||
| SliverToBoxAdapter( | |||
| child: HomeGoods(), | |||
| ), | |||
| ]; | |||
| } | |||
| @override | |||
| List<Widget> createSkeleton(Map<String, dynamic> model) { | |||
| return [ | |||
| _createHeaderSkeleton(), | |||
| _createBodySkeleton(), | |||
| ]; | |||
| } | |||
| Widget _createHeader(TabController controller) { | |||
| return SliverPersistentHeader( | |||
| pinned: true, | |||
| floating: false, | |||
| delegate: HomeGoodsDelegate(controller), | |||
| ); | |||
| } | |||
| Widget _createHeaderSkeleton() { | |||
| return SliverPersistentHeader( | |||
| SliverPersistentHeader( | |||
| pinned: true, | |||
| floating: false, | |||
| delegate: HomeGoodsHeaderSkeletonDelegate(), | |||
| ); | |||
| } | |||
| Widget _createBody(TabController controller) { | |||
| return SliverToBoxAdapter( | |||
| child: HomeGoods(), | |||
| ); | |||
| } | |||
| Widget _createBodySkeleton() { | |||
| return SliverToBoxAdapter( | |||
| ), | |||
| SliverToBoxAdapter( | |||
| child: HomeGoodsSkeleton(), | |||
| ); | |||
| ), | |||
| ]; | |||
| } | |||
| @override | |||
| bool isSliverChild() { | |||
| return true; | |||
| @@ -1,9 +1,6 @@ | |||
| import 'package:flutter/material.dart'; | |||
| class HomeGoodsDelegate extends SliverPersistentHeaderDelegate { | |||
| final TabController controller; | |||
| HomeGoodsDelegate(this.controller); | |||
| @override | |||
| Widget build( | |||
| @@ -13,7 +10,7 @@ class HomeGoodsDelegate extends SliverPersistentHeaderDelegate { | |||
| color: Colors.red, | |||
| alignment: Alignment.center, | |||
| child: TabBar( | |||
| controller: controller, | |||
| controller: TabController(initialIndex: 0, length: 6, vsync: ScrollableState()), | |||
| isScrollable: true, | |||
| tabs: <Widget>[ | |||
| Tab(icon: Icon(Icons.local_florist)), | |||
| @@ -28,10 +25,10 @@ class HomeGoodsDelegate extends SliverPersistentHeaderDelegate { | |||
| } | |||
| @override | |||
| double get maxExtent => 60.0; | |||
| double get maxExtent => 64.0; | |||
| @override | |||
| double get minExtent => 60.0; | |||
| double get minExtent => 64.0; | |||
| @override | |||
| bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => | |||
| @@ -16,6 +16,8 @@ dependencies: | |||
| provider: ^4.0.0 | |||
| bloc: ^4.0.0 | |||
| flutter_bloc: ^4.0.1 | |||
| event_bus: ^1.1.1 | |||
| pull_to_refresh: ^1.6.1 | |||
| dev_dependencies: | |||
| flutter_test: | |||