|
- import 'dart:convert';
-
- import 'package:flutter/cupertino.dart';
- import 'package:pull_to_refresh/pull_to_refresh.dart';
- import 'package:tab_indicator_styler/tab_indicator_styler.dart';
- import 'package:zhiying_base_widget/pages/custom_page/custom_item_page.dart';
- import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_bg_notifier.dart';
- import 'package:zhiying_base_widget/widgets/custom/search/custom_search_widget.dart';
- import 'package:zhiying_base_widget/widgets/empty/empty_widget.dart';
- import 'package:zhiying_base_widget/widgets/others/mine_header_bg_widget.dart';
- import 'package:zhiying_comm/zhiying_comm.dart';
- import 'package:flutter/material.dart';
- import 'package:provider/provider.dart';
- import 'package:flutter_bloc/flutter_bloc.dart';
- import 'bloc/custom_page_bloc.dart';
- import 'bloc/custom_page_state.dart';
- import 'bloc/custom_page_event.dart';
- import 'bloc/custom_page_repository.dart';
- import 'dart:ui';
- import 'package:fluttertoast/fluttertoast.dart';
-
- ///
- /// 通用模块页面
- ///
- class CustomPage extends StatefulWidget {
- final Map<String, dynamic> data;
-
- CustomPage(this.data, {Key key}) : super(key: key);
-
- @override
- _CustomPageState createState() => _CustomPageState();
- }
-
- class _CustomPageState extends State<CustomPage> {
- @override
- Widget build(BuildContext context) {
- return MultiProvider(
- providers: [
- ChangeNotifierProvider.value(value: MainPageBgNotifier()),
- ],
- child: BlocProvider<CustomPageBloc>(
- create: (_) => CustomPageBloc(CustomPageRepository(data: widget?.data))..add(CustomPageInitEvent()),
- child: _CommonPageContainer(widget?.data),
- // ),
- ),
- );
- }
- }
-
- class _CommonPageContainer extends StatefulWidget {
- final Map<String, dynamic> data;
-
- _CommonPageContainer(this.data);
-
- @override
- __CommonPageContainerState createState() => __CommonPageContainerState();
- }
-
- class __CommonPageContainerState extends State<_CommonPageContainer> with SingleTickerProviderStateMixin {
- TabController _tabController;
-
- // 是否有AppBar
- bool _isHasAppbar = false;
-
- // 是否有TabBar
- bool _isHasTabBar = false;
-
- /// 刷新
- void _onRefreshEvent() async {
- BlocProvider.of<CustomPageBloc>(context).add(CustomPageRefreshEvent());
- }
-
- @override
- void dispose() {
- _tabController?.dispose();
- super.dispose();
- }
-
- @override
- Widget build(BuildContext context) {
- return MediaQuery.removePadding(
- context: context,
- child: BlocConsumer<CustomPageBloc, CustomPageState>(
- listener: (context, state) {},
- buildWhen: (prev, current) {
- if (current is CustomPageErrorState) {
- return false;
- }
- if (current is CustomPageRefreshSuccessState) {
- // _refreshController.refreshCompleted(resetFooterState: true);
- return false;
- }
- if (current is CustomPageRefreshErrorState) {
- // _refreshController.refreshFailed();
- return false;
- }
- return true;
- },
- builder: (context, state) {
- /// 有数据
- if (state is CustomPageLoadedState) {
- if (EmptyUtil.isEmpty(state.model)) return _buildEmptyWidget();
- return _buildMainWidget(state.model);
- }
-
- /// 初始化失败
- if (state is CustomPageInitErrorState) {
- return _buildEmptyWidget();
- }
-
- /// 骨架图
- return _buildSkeletonWidget();
- },
- ),
- );
- }
-
- /// 有数据
- Widget _buildMainWidget(List<Map<String, dynamic>> model) {
- return Stack(
- children: <Widget>[
- Scaffold(
- appBar: _buildAppbar(model?.first),
- backgroundColor: HexColor.fromHex('#F9F9F9'),
- // floatingActionButton: _buildFloatWidget(),
- floatingActionButtonLocation: _CustomFloatingActionButtonLocation(FloatingActionButtonLocation.endFloat, 0, -100),
- body: Column(children: _buildFirstWidget(model)),
- ),
- ],
- );
- }
-
- /// 骨架图
- Widget _buildSkeletonWidget() {
- return Scaffold();
- }
-
- /// 空数据视图
- Widget _buildEmptyWidget() {
- return Scaffold(
- backgroundColor: HexColor.fromHex('#F9F9F9'),
- appBar: AppBar(
- brightness: Brightness.light,
- backgroundColor: Colors.white,
- leading: IconButton(
- icon: Icon(
- Icons.arrow_back_ios,
- size: 22,
- color: HexColor.fromHex('#333333'),
- ),
- onPressed: () => Navigator.maybePop(context),
- ),
- title: Text(
- '',
- style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 18, fontWeight: FontWeight.bold),
- ),
- centerTitle: true,
- elevation: 0,
- ),
- body: Column(
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- Align(
- alignment: Alignment.topCenter,
- child: EmptyWidget(
- tips: '网络似乎开小差了~',
- ),
- ),
- GestureDetector(
- onTap: () => _onRefreshEvent(),
- behavior: HitTestBehavior.opaque,
- child: Container(
- alignment: Alignment.center,
- decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), border: Border.all(color: HexColor.fromHex('#999999'), width: 0.5), color: Colors.white),
- width: 80,
- height: 20,
- child: Text(
- '刷新一下',
- style: TextStyle(fontSize: 12, color: HexColor.fromHex('#333333'), fontWeight: FontWeight.bold),
- ),
- ),
- )
- ],
- ));
- }
-
- /// 数据,生成第一层widget
- List<Widget> _buildFirstWidget(List<Map<String, dynamic>> model) {
- List<Widget> result = [];
-
- // 分类导航的key ⚠️ 这里先写成Test 后续要改
- const String CATEGORY_KEY = 'category';
- // 判断是否有分类导航
- // 判断最后一个是否属于分类导航,如果属于,则有分类导航,如果不是,则无分类导航
- bool haveCategory = !EmptyUtil.isEmpty(model?.last) && model.last.containsKey('mod_name') && model.last['mod_name'] == CATEGORY_KEY;
- int endIndexLength = model.length;
- // 如果没有分类导航,则取分类导航之上的所有mod
- if (!haveCategory) {
- for (int i = 0; i < model.length; i++) {
- Map<String, dynamic> item = model[i];
- if (item['mod_name'] == CATEGORY_KEY) {
- endIndexLength = (i + 1);
- break;
- }
- }
- }
-
- for (int i = 0; i < endIndexLength; i++) {
- WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(model[i]));
- // last model
- if (i == endIndexLength - 1) {
- result.addAll(_buildTabBar(model[i], i));
- break;
- }
-
- // appBar 无需在这里添加
- if (item.modName.contains('appbar')) {
- continue;
- }
- result.addAll(WidgetFactory.create(item.modName, isSliver: false, model: model[i]));
- }
-
- // 没有appbar并且没有tabbar,则给第一个元素加边距
- if (!_isHasAppbar && !_isHasTabBar) {
- result.insert(0, SizedBox(height: MediaQueryData.fromWindow(window).padding.top, child: Container(color: HexColor.fromHex('#FF4242'),),));
- }
-
- return result;
- }
-
- /// appbar
- Widget _buildAppbar(final Map<String, dynamic> model) {
- if (EmptyUtil.isEmpty(model)) return null;
- String mobName = model['mod_name'];
- if (!mobName.contains('_appbar')) return null;
- Map<String, dynamic> data = Map<String, dynamic>();
- try {
- data = jsonDecode(model['data']);
- } catch (e, s) {
- Logger.warn(e, s);
- }
- String parentTitle = !EmptyUtil.isEmpty(widget?.data) ? widget?.data['title'] ?? '' : '';
- _isHasAppbar = true;
- return AppBar(
- backgroundColor: HexColor.fromHex(null != data ? data['app_bar_bg_color'] ?? '#FFFFFF' : '#FFFFFF'),
- brightness: Brightness.light,
- leading: IconButton(
- icon: Icon(
- Icons.arrow_back_ios,
- size: 22,
- color: HexColor.fromHex('#333333'),
- ),
- onPressed: () => Navigator.maybePop(context),
- ),
- title: Text(
- null != data && data.containsKey('app_bar_name') ? data['app_bar_name'] != '自定义页面' ? data['app_bar_name'] : parentTitle : parentTitle,
- style: TextStyle(
- color: HexColor.fromHex(null != data ? data['app_bar_name_color'] ?? '#333333' : '#333333'),
- fontSize: 16,
- fontWeight: FontWeight.bold,
- ),
- ),
- centerTitle: true,
- elevation: 0,
- );
- }
-
- /// tabBar
- List<Widget> _buildTabBar(final Map<String, dynamic> model, final int index) {
- Map<String, dynamic> data = Map<String, dynamic>();
- List<Map<String, dynamic>> listStyle = [];
- List<Widget> result = [];
- try {
- data = jsonDecode(model['data']);
- listStyle = List.from(data['list_style']);
- } catch (e, s) {
- Logger.warn(e, s);
- }
-
- // 1、导航栏没开启的情况 传null进去进行获取没开启导航栏的widget集合
- if (EmptyUtil.isEmpty(listStyle)) {
- result.add(Expanded(
- child: CustomItemPage(null, 0, model['mod_id']?.toString() ?? null, model['mod_pid']?.toString() ?? null, (!_isHasAppbar && index == 0 )),
- ));
- return result;
- }
-
- // 2、导航栏开启的情况
- if (listStyle.length > 0) {
- // tabContorller 初始化
- if (null == _tabController || _tabController.length != listStyle.length) {
- _tabController = new TabController(length: listStyle.length, vsync: this);
- }
-
- result.add(Container(
- height: 40,
- width: double.infinity,
- color: HexColor.fromHex(data['bg_color']),
- child: TabBar(
- controller: _tabController,
- isScrollable: /*listStyle.length <= 5 ? false : */ true,
- labelColor: HexColor.fromHex(data['choose_text_color'] ?? '#FF4242'),
- labelStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
- unselectedLabelColor: HexColor.fromHex(data['text_color'] ?? '#999999'),
- unselectedLabelStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
- indicatorSize: TabBarIndicatorSize.label,
- indicator: MaterialIndicator(
- color: HexColor.fromHex(data['choose_color'] ?? '#FF4242'),
- bottomLeftRadius: 1.25,
- topLeftRadius: 1.25,
- topRightRadius: 1.25,
- bottomRightRadius: 1.25,
- height: 2.5,
- horizontalPadding: 5,
- ),
- tabs: listStyle.map((e) => Text(e['name'])).toList(),
- ),
- ));
-
- _isHasTabBar = true;
- // 最后添加TabBarView
- result.add(Expanded(
- child: TabBarView(
- controller: _tabController,
- children: _buildTabBarViewChildren(listStyle, model['mod_id']?.toString(), model['mod_pid']?.toString(), index),
- ),
- ));
- }
- return result;
- }
-
- /// 返回TabBarView的视图
- List<Widget> _buildTabBarViewChildren(final List<Map<String, dynamic>> listStyle, final String modId, final String modPid, final int index) {
- List<Widget> result = [];
- for (int i = 0; i < listStyle.length; i++) {
- result.add(CustomItemPage(listStyle[i], i, modId, modPid, (!_isHasAppbar && !_isHasTabBar && index == 0 )));
- }
- return result;
- }
-
- // /// 悬浮按钮
- // Widget _buildFloatWidget() {
- // return Visibility(
- // visible: true,
- // child: GestureDetector(
- // onTap: () => _scrollTop(),
- // behavior: HitTestBehavior.opaque,
- // child: Container(
- // height: 30,
- // width: 30,
- // child: Icon(Icons.arrow_upward),
- // ),
- // ),
- // );
- // }
-
- }
-
- /// 回到顶部的icon
- class _CustomFloatingActionButtonLocation extends FloatingActionButtonLocation {
- FloatingActionButtonLocation location;
- double offsetX; // X方向的偏移量
- double offsetY; // Y方向的偏移量
- _CustomFloatingActionButtonLocation(this.location, this.offsetX, this.offsetY);
-
- @override
- Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) {
- Offset offset = location.getOffset(scaffoldGeometry);
- return Offset(offset.dx + offsetX, offset.dy + offsetY);
- }
- }
|