@@ -181,6 +181,12 @@ | |||||
"packageUri": "lib/", | "packageUri": "lib/", | ||||
"languageVersion": "2.0" | "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", | "name": "file", | ||||
"rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/file-5.2.1", | "rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/file-5.2.1", | ||||
@@ -463,6 +469,12 @@ | |||||
"packageUri": "lib/", | "packageUri": "lib/", | ||||
"languageVersion": "2.2" | "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", | "name": "quiver", | ||||
"rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/quiver-2.0.5", | "rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/quiver-2.0.5", | ||||
@@ -668,7 +680,7 @@ | |||||
"languageVersion": "2.1" | "languageVersion": "2.1" | ||||
} | } | ||||
], | ], | ||||
"generated": "2020-09-04T06:52:20.100476Z", | |||||
"generated": "2020-09-07T03:45:53.992384Z", | |||||
"generator": "pub", | "generator": "pub", | ||||
"generatorVersion": "2.7.2" | "generatorVersion": "2.7.2" | ||||
} | } |
@@ -1,11 +1,20 @@ | |||||
import 'package:flutter/cupertino.dart'; | import 'package:flutter/cupertino.dart'; | ||||
import 'package:flutter/material.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_notifier.dart'; | ||||
import 'package:zhiying_base_widget/pages/main_page/main_page_sk.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | import 'package:zhiying_comm/zhiying_comm.dart'; | ||||
import 'package:provider/provider.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 { | class MainPage extends StatefulWidget { | ||||
MainPage({Key key}) : super(key: key); | |||||
final Map<String, dynamic> data; | |||||
MainPage( | |||||
this.data, { | |||||
Key key, | |||||
}) : super(key: key); | |||||
@override | @override | ||||
_MainPageState createState() => _MainPageState(); | _MainPageState createState() => _MainPageState(); | ||||
@@ -18,23 +27,49 @@ class _MainPageState extends State<MainPage> { | |||||
backgroundColor: Color(0xfff9f9f9), | backgroundColor: Color(0xfff9f9f9), | ||||
body: ChangeNotifierProvider( | body: ChangeNotifierProvider( | ||||
create: (context) => MainPageNotifier(), | 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 | @override | ||||
_MainPageContainerState createState() => _MainPageContainerState(); | _MainPageContainerState createState() => _MainPageContainerState(); | ||||
} | } | ||||
class _MainPageContainerState extends State<MainPageContainer> { | |||||
class _MainPageContainerState extends State<_MainPageContainer> { | |||||
WidgetType _type = WidgetType.normal; | WidgetType _type = WidgetType.normal; | ||||
bool _isEnded = false; | bool _isEnded = false; | ||||
ScrollController _controller = ScrollController(); | 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 | @override | ||||
void dispose() { | void dispose() { | ||||
@@ -44,6 +79,7 @@ class _MainPageContainerState extends State<MainPageContainer> { | |||||
@override | @override | ||||
void initState() { | void initState() { | ||||
_bloc = BlocProvider.of<MainPageBloc>(context); | |||||
_reload(); | _reload(); | ||||
_controller.addListener(() { | _controller.addListener(() { | ||||
// print('${_controller.offset} ${_controller.position.maxScrollExtent}'); | // print('${_controller.offset} ${_controller.position.maxScrollExtent}'); | ||||
@@ -65,11 +101,16 @@ class _MainPageContainerState extends State<MainPageContainer> { | |||||
setState(() { | setState(() { | ||||
_type = WidgetType.skeleton; | _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) { | List<Widget> _createContent(BuildContext context) { | ||||
@@ -94,11 +135,47 @@ class _MainPageContainerState extends State<MainPageContainer> { | |||||
@override | @override | ||||
Widget build(BuildContext context) { | 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() { | static void registPage() { | ||||
PageFactory.regist('homePage', (model) => HomePage()); | 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_header_sk.dart'; | ||||
import 'package:zhiying_base_widget/widgets/home_goods/skeleton/home_goods_sk.dart'; | import 'package:zhiying_base_widget/widgets/home_goods/skeleton/home_goods_sk.dart'; | ||||
import 'package:zhiying_comm/zhiying_comm.dart'; | import 'package:zhiying_comm/zhiying_comm.dart'; | ||||
import 'package:event_bus/event_bus.dart'; | |||||
class GoodsListCreater extends WidgetCreater { | class GoodsListCreater extends WidgetCreater { | ||||
@override | @override | ||||
List<Widget> createWidgets(Map<String, dynamic> model) { | List<Widget> createWidgets(Map<String, dynamic> model) { | ||||
TabController controller = | |||||
TabController(initialIndex: 0, length: 6, vsync: ScrollableState()); | |||||
EventBus eventBus = EventBus(); | |||||
return [ | return [ | ||||
_createHeader(controller), | |||||
_createBody(controller), | |||||
SliverPersistentHeader( | |||||
pinned: true, | |||||
floating: false, | |||||
delegate: HomeGoodsDelegate(), | |||||
), | |||||
SliverToBoxAdapter( | |||||
child: HomeGoods(), | |||||
), | |||||
]; | ]; | ||||
} | } | ||||
@override | @override | ||||
List<Widget> createSkeleton(Map<String, dynamic> model) { | List<Widget> createSkeleton(Map<String, dynamic> model) { | ||||
return [ | return [ | ||||
_createHeaderSkeleton(), | |||||
_createBodySkeleton(), | |||||
]; | |||||
} | |||||
Widget _createHeader(TabController controller) { | |||||
return SliverPersistentHeader( | |||||
pinned: true, | |||||
floating: false, | |||||
delegate: HomeGoodsDelegate(controller), | |||||
); | |||||
} | |||||
Widget _createHeaderSkeleton() { | |||||
return SliverPersistentHeader( | |||||
SliverPersistentHeader( | |||||
pinned: true, | pinned: true, | ||||
floating: false, | floating: false, | ||||
delegate: HomeGoodsHeaderSkeletonDelegate(), | delegate: HomeGoodsHeaderSkeletonDelegate(), | ||||
); | |||||
} | |||||
Widget _createBody(TabController controller) { | |||||
return SliverToBoxAdapter( | |||||
child: HomeGoods(), | |||||
); | |||||
} | |||||
Widget _createBodySkeleton() { | |||||
return SliverToBoxAdapter( | |||||
), | |||||
SliverToBoxAdapter( | |||||
child: HomeGoodsSkeleton(), | child: HomeGoodsSkeleton(), | ||||
); | |||||
), | |||||
]; | |||||
} | } | ||||
@override | @override | ||||
bool isSliverChild() { | bool isSliverChild() { | ||||
return true; | return true; | ||||
@@ -1,9 +1,6 @@ | |||||
import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
class HomeGoodsDelegate extends SliverPersistentHeaderDelegate { | class HomeGoodsDelegate extends SliverPersistentHeaderDelegate { | ||||
final TabController controller; | |||||
HomeGoodsDelegate(this.controller); | |||||
@override | @override | ||||
Widget build( | Widget build( | ||||
@@ -13,7 +10,7 @@ class HomeGoodsDelegate extends SliverPersistentHeaderDelegate { | |||||
color: Colors.red, | color: Colors.red, | ||||
alignment: Alignment.center, | alignment: Alignment.center, | ||||
child: TabBar( | child: TabBar( | ||||
controller: controller, | |||||
controller: TabController(initialIndex: 0, length: 6, vsync: ScrollableState()), | |||||
isScrollable: true, | isScrollable: true, | ||||
tabs: <Widget>[ | tabs: <Widget>[ | ||||
Tab(icon: Icon(Icons.local_florist)), | Tab(icon: Icon(Icons.local_florist)), | ||||
@@ -28,10 +25,10 @@ class HomeGoodsDelegate extends SliverPersistentHeaderDelegate { | |||||
} | } | ||||
@override | @override | ||||
double get maxExtent => 60.0; | |||||
double get maxExtent => 64.0; | |||||
@override | @override | ||||
double get minExtent => 60.0; | |||||
double get minExtent => 64.0; | |||||
@override | @override | ||||
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => | bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => | ||||
@@ -16,6 +16,8 @@ dependencies: | |||||
provider: ^4.0.0 | provider: ^4.0.0 | ||||
bloc: ^4.0.0 | bloc: ^4.0.0 | ||||
flutter_bloc: ^4.0.1 | flutter_bloc: ^4.0.1 | ||||
event_bus: ^1.1.1 | |||||
pull_to_refresh: ^1.6.1 | |||||
dev_dependencies: | dev_dependencies: | ||||
flutter_test: | flutter_test: | ||||