import 'package:flutter/cupertino.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:zhiying_base_widget/widgets/empty/empty_widget.dart'; import 'package:zhiying_base_widget/widgets/refresh/refresh_header/refresh_header.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:zhiying_comm/util/custom_sliver_persistent_header_delegate.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'; /// /// 通用模块页面 /// class CustomPage extends StatelessWidget { final Map data; CustomPage(this.data, {Key key}) : super(key: key); @override Widget build(BuildContext context) { // return NestedScrollDemoPage(); return BlocProvider( create: (_) => CustomPageBloc(CustomPageRepository(data: data))..add(CustomPageInitEvent()), child: _CommonPageContainer(), // ), ); } } class _CommonPageContainer extends StatefulWidget { @override __CommonPageContainerState createState() => __CommonPageContainerState(); } class __CommonPageContainerState extends State<_CommonPageContainer> with SingleTickerProviderStateMixin { ScrollController _controller; ScrollController _controller2; RefreshController _refreshController; TabController _tabController; bool _isEnded = false; /// 回到顶点 void _scrollTop() { // _controller.jumpTo(0); _controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.linear); } /// 刷新 void _onRefreshEvent() async { BlocProvider.of(context).add(CustomPageRefreshEvent()); } /// 加载更多 void _onLoadEvent() async {} @override void initState() { _controller = ScrollController(); _controller2 = ScrollController(); _refreshController = RefreshController(initialRefresh: false); _tabController = TabController(length: 10, vsync: this); super.initState(); } @override void dispose() { _controller?.dispose(); _refreshController?.dispose(); _tabController?.dispose(); _controller2?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return MediaQuery.removePadding( context: context, child: BlocConsumer( 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) { // return _buildMain2Widget(); // } // if (state is CustomPageInitErrorState) { // return _buildMain2Widget(); // } // return _buildMain2Widget(); return _buildMain2Widget(); }, ), ); } /// 有数据 Widget _buildMainWidget() { double top = MediaQueryData.fromWindow(window).padding.top; return Scaffold( backgroundColor: HexColor.fromHex('#F9F9F9'), floatingActionButton: _buildFloatWidget(), floatingActionButtonLocation: _CustomFloatingActionButtonLocation(FloatingActionButtonLocation.endFloat, 0, -100), body: SmartRefresher( enablePullDown: true, enablePullUp: false, header: RefreshHeader( offsetY: top, ), controller: _refreshController, onLoading: _onLoadEvent, onRefresh: _onRefreshEvent, child: CustomScrollView( key: UniqueKey(), controller: _controller, slivers: [ /// 标题 SliverAppBar( title: Text('标题'), centerTitle: true, pinned: true, ), /// 轮播图 _buildSliverBanner(), /// 搜索 _buildSearch(), /// TAB BAR _buildTabbar(), SliverFillRemaining( child: TabBarView( controller: _tabController, children: List.generate(10, (index) => Container( height: double.infinity, width: double.infinity, color: Colors.white, child: MediaQuery.removePadding( context: context, removeTop: true, child: CustomScrollView( controller: _controller2, key: UniqueKey(), slivers: [ _buildQucikEntry(), _buildSearch(), _buildSliverBanner(), _buildGoodsList(), ], ), ), )), ), ) ], ), ), ); } /// 有数据2 Widget _buildMain2Widget(){ return Scaffold( appBar: AppBar(title: Text('标题'),centerTitle: true,), backgroundColor: HexColor.fromHex('#F9F9F9'), floatingActionButton: _buildFloatWidget(), floatingActionButtonLocation: _CustomFloatingActionButtonLocation(FloatingActionButtonLocation.endFloat, 0, -100), body: Column( children: [ Container(height: 40, width: double.infinity, color: Colors.green,), Container( height: 40, width: double.infinity, color: Colors.red, child: TabBar( isScrollable: true, controller: _tabController, tabs: List.generate(10, (index) => Text('$index')), ), ), Expanded( child: TabBarView( controller: _tabController, children: List.generate(10, (index) => Container( height: double.infinity, width: double.infinity, color: Colors.white, child: MediaQuery.removePadding( context: context, removeTop: true, child: CustomScrollView( controller: _controller, key: UniqueKey(), slivers: [ _buildQucikEntry(), _buildSearch(), _buildSliverBanner(), _buildSearch(title: '商品列表'), _buildGoodsList(), ], ), ), )), ), ) ], ), ); } /// tabBar Widget _buildTabbar(){ return SliverPersistentHeader( delegate: CustomSliverPersistentHeaderDelegate( max: 40, min: 40, child: Container( height: double.infinity, width: double.infinity, color: Colors.redAccent, child: TabBar( isScrollable: true, controller: _tabController, tabs: List.generate(10, (index) => Text('$index')), ), ), ), pinned: true, ); } /// 多眼导航 Widget _buildQucikEntry(){ return SliverToBoxAdapter( child: Container( alignment: Alignment.center, child: Text('多眼导航'), height: 70, width: double.infinity, color: Colors.green, ), ); } /// 搜索 Widget _buildSearch({String title}){ return SliverPersistentHeader( delegate: CustomSliverPersistentHeaderDelegate( max: 40, min: 40, child: Container( alignment: Alignment.center, child: Text(title ?? '搜索'), height: double.infinity, width: double.infinity, color: Colors.blueAccent, ), ), pinned: true, ); } /// 商品列表 Widget _buildGoodsList(){ return SliverList( delegate: SliverChildBuilderDelegate((context, index) { return Container( height: 50, width: double.infinity, color: Colors.green[(index % 9 + 1) * 100], ); }, childCount: 50)); } /// 轮播图 Widget _buildSliverBanner(){ return SliverPersistentHeader( delegate: CustomSliverPersistentHeaderDelegate( max: 140, min: 140, child: Container( child: Text('轮播图'), alignment: Alignment.center, height: double.infinity, width: double.infinity, color: Colors.yellowAccent, ), ), pinned: false, ); } /// 悬浮按钮 Widget _buildFloatWidget() { return Visibility( visible: true, child: GestureDetector( onTap: ()=> _scrollTop(), behavior: HitTestBehavior.opaque, child: Container( height: 30, width: 30, color: Colors.redAccent, ), ), ); } /// 骨架图 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: 15, fontWeight: FontWeight.bold), ), centerTitle: true, elevation: 0, ), body: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ 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), ), ), ) ], )); } } 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); } }