From 77b353735cdb37924eb6309febee3dcd82da7e33 Mon Sep 17 00:00:00 2001 From: zhangmeng <494089941@qq.com> Date: Sun, 23 Jan 2022 14:19:20 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5bar=E7=9A=84=E9=A2=9C?= =?UTF-8?q?=E8=89=B2=E9=9A=8F=E8=BD=AE=E6=92=AD=E5=9B=BE=E5=8F=98=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/home/home_page.dart | 702 +++++++++++-------- lib/pages/home/widget/animate_app_bar.dart | 91 ++- lib/pages/home/widget/filter_tool_bar.dart | 592 ---------------- lib/pages/home/widget/home_search.dart | 54 -- lib/ui/community/activity/activity_card.dart | 16 +- pubspec.lock | 7 + pubspec.yaml | 2 + 7 files changed, 469 insertions(+), 995 deletions(-) delete mode 100644 lib/pages/home/widget/filter_tool_bar.dart delete mode 100644 lib/pages/home/widget/home_search.dart diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart index a6e93ff5..e3574593 100644 --- a/lib/pages/home/home_page.dart +++ b/lib/pages/home/home_page.dart @@ -1,13 +1,11 @@ // Dart imports: -import 'package:aku_new_community/const/resource.dart'; import 'package:aku_new_community/constants/api.dart'; import 'package:aku_new_community/constants/application_objects.dart'; import 'package:aku_new_community/model/common/img_model.dart'; import 'package:aku_new_community/model/community/activity_item_model.dart'; import 'package:aku_new_community/model/community/board_model.dart'; import 'package:aku_new_community/model/community/swiper_model.dart'; -import 'package:aku_new_community/pages/home/widget/animate_app_bar.dart'; import 'package:aku_new_community/pages/message_center_page/message_center_page.dart'; import 'package:aku_new_community/pages/one_alarm/widget/alarm_page.dart'; import 'package:aku_new_community/pages/visitor_access_page/visitor_access_page.dart'; @@ -27,18 +25,16 @@ import 'package:aku_new_community/widget/others/rectIndicator.dart'; import 'package:aku_new_community/widget/others/user_tool.dart'; import 'package:badges/badges.dart'; import 'package:bot_toast/bot_toast.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart'; import 'package:get/get.dart'; import 'package:jpush_flutter/jpush_flutter.dart'; +import 'package:palette_generator/palette_generator.dart'; import 'package:power_logger/power_logger.dart'; import 'package:provider/provider.dart'; -import 'package:velocity_x/velocity_x.dart'; - -import 'widget/home_search.dart'; class HomePage extends StatefulWidget { HomePage({Key? key}) : super(key: key); @@ -66,6 +62,9 @@ class _HomePageState extends State List _activityItemModels = []; List _boardItemModels = []; List _swiperModels = []; + SwiperController _swiperController = SwiperController(); + + ValueNotifier _barColor = ValueNotifier(Colors.transparent); @override void initState() { @@ -81,12 +80,15 @@ class _HomePageState extends State } _scrollController = ScrollController(); _refreshController = EasyRefreshController(); + SystemChrome.setSystemUIOverlayStyle( + SystemUiOverlayStyle(statusBarColor: Colors.transparent)); } @override void dispose() { _refreshController.dispose(); _scrollController?.dispose(); + _swiperController.dispose(); super.dispose(); } @@ -97,11 +99,51 @@ class _HomePageState extends State commentCount = appProvider.messageCenterModel.commentCount ?? 0; sysCount = appProvider.messageCenterModel.sysCount ?? 0; sum = commentCount + sysCount; - return Scaffold( - extendBodyBehindAppBar: true, - appBar: AnimateAppBar( - scrollController: _scrollController, - actions: [ + var head = ValueListenableBuilder( + valueListenable: _barColor, + builder: (context, Color color, child) { + return Container( + padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), + decoration: BoxDecoration( + border: Border.all(width: 0, color: color), + color: color, + ), + width: double.infinity, + child: child, + ); + }, + child: Padding( + padding: EdgeInsets.symmetric(vertical: 16.w, horizontal: 16.w), + child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ + if (appProvider.location != null) + Padding( + padding: const EdgeInsets.only(right: 5), + child: Image.asset( + R.ASSETS_ICONS_ICON_MAIN_LOCATION_PNG, + width: 32.w, + height: 32.w, + ), + ), + Text( + appProvider.location?['city'] == null + ? '' + : appProvider.location?['city'] as String? ?? '', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 24.sp, + color: Color(0xff333333), + ), + textAlign: TextAlign.center, + ), + Text( + '(${appProvider.weatherType} ${appProvider.weatherTemp}℃)', + style: TextStyle( + fontSize: 24.sp, + color: Color(0xff999999), + ), + textAlign: TextAlign.center, + ), + Spacer(), GestureDetector( onTap: () { Get.to(() => BeeSearch()); @@ -134,311 +176,303 @@ class _HomePageState extends State height: 40.w, width: 40.w), )), ), - ], + ]), ), - // floatingActionButton: FloatingActionButton( - // - // child: Container( - // decoration: BoxDecoration( - // image: DecorationImage( - // fit: BoxFit.fill, - // image: - // AssetImage(R.ASSETS_ICONS_ICON_MAIN_OPEN_PNG),) - // ), - // ), - // onPressed: (){ - // print('FloatingActionButton'); - // }, - // ), - body: Stack( - children: [ - EasyRefresh( - controller: _refreshController, - header: MaterialHeader(), - firstRefresh: true, - onRefresh: () async { - //_activityItemModel = await CommunityFunc.activity(); - _activityItemModels = await CommunityFunc.activityList(); - _boardItemModels = await CommunityFunc.board(); - _swiperModels = await CommunityFunc.swiper(); - appProvider.getMessageCenter(); - setState(() {}); - }, - child: CustomScrollView( - controller: _scrollController, - slivers: [ - SliverToBoxAdapter( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - HomeSearch(), - - HomeSwiper(), //要做点击事件 - // SizedBox(height: 100.w), - Container( - padding: EdgeInsets.only(top: 24.w, bottom: 32.w), - child: getFunction(), //ApplicationView(), - decoration: BoxDecoration( - color: Colors.white, - boxShadow: const [ - BoxShadow( - color: Color(0x14000000), - blurRadius: 0, - offset: Offset(0.0, 2.0), - spreadRadius: 0.1) - ], - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(28), - bottomRight: Radius.circular(28))), - ) - //ApplicationBox(child: ApplicationView()), - ], - ), - ), - SliverToBoxAdapter( - child: Container( - height: 40, - margin: - EdgeInsets.only(left: 32.w, right: 32.w, top: 24.w), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(8)), - boxShadow: const [ - BoxShadow( - color: Color(0x14000000), - blurRadius: 4, - spreadRadius: 0.5) - ], - ), - child: HomeNotification(items: _boardItemModels)), - ), - SliverToBoxAdapter( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - GestureDetector( - child: Container( - margin: EdgeInsets.only(top: 24.w), - padding: EdgeInsets.only(left: 32.w, top: 24.w), - width: 140, - height: 150, - decoration: BoxDecoration( - image: DecorationImage( - fit: BoxFit.fill, - image: AssetImage(R.ASSETS_IMAGES_CARD_YELLOW_PNG), - )), + ); + return AnnotatedRegion( + value: SystemUiOverlayStyle.dark, + child: Scaffold( + extendBody: true, + extendBodyBehindAppBar: true, + body: Stack( + children: [ + Column( + children: [ + head, + Flexible( + child: EasyRefresh( + controller: _refreshController, + header: BeeBallPauseHeader(bgColor: _barColor), + firstRefresh: true, + onRefresh: () async { + //_activityItemModel = await CommunityFunc.activity(); + _activityItemModels = await CommunityFunc.activityList(); + _boardItemModels = await CommunityFunc.board(); + _swiperModels = await CommunityFunc.swiper(); + appProvider.getMessageCenter(); + setState(() {}); + }, + child: CustomScrollView( + controller: _scrollController, + slivers: [ + SliverToBoxAdapter( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ - Text( - '访客邀请', - style: TextStyle( - color: Color(0xD9000000), - fontSize: 26.sp, - fontWeight: FontWeight.bold), - ), - 10.hb, - Text( - '一键分享', - style: TextStyle( - color: Color(0x73000000), - fontSize: 20.sp, - ), - ), - Text( - '让拜访不再是难事', - style: TextStyle( - color: Color(0x73000000), - fontSize: 20.sp, - ), - ), - Spacer(), - Image.asset( - R.ASSETS_ICONS_ICON_MAIN_INVITE_PNG, - width: 100.w, - height: 100.w, - ), - 30.hb, + HomeSwiper(), //要做点击事件 + // SizedBox(height: 100.w), + Container( + padding: + EdgeInsets.only(top: 24.w, bottom: 32.w), + child: getFunction(), //ApplicationView(), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: const [ + BoxShadow( + color: Color(0x14000000), + blurRadius: 0, + offset: Offset(0.0, 2.0), + spreadRadius: 0.1) + ], + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(28), + bottomRight: Radius.circular(28))), + ) + //ApplicationBox(child: ApplicationView()), ], ), ), - onTap: () { - Get.to(VisitorAccessPage()); - }, - ), - 25.wb, - Container( - margin: EdgeInsets.only(top: 24.w), - child: Column( - children: [ - GestureDetector( - child: Container( - width: 190, - height: 69, - decoration: BoxDecoration( - image: DecorationImage( - fit: BoxFit.fill, - image: - AssetImage(R.ASSETS_IMAGES_CARD_PINK_PNG), - )), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - 20.wb, - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - 20.hb, - Text( - '一键报警', - style: TextStyle( - color: Color(0xD9000000), - fontSize: 26.sp, - fontWeight: FontWeight.bold), + SliverToBoxAdapter( + child: Container( + height: 40, + margin: EdgeInsets.only( + left: 32.w, right: 32.w, top: 24.w), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.all(Radius.circular(8)), + boxShadow: const [ + BoxShadow( + color: Color(0x14000000), + blurRadius: 4, + spreadRadius: 0.5) + ], + ), + child: HomeNotification(items: _boardItemModels)), + ), + SliverToBoxAdapter( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Container( + margin: EdgeInsets.only(top: 24.w), + padding: + EdgeInsets.only(left: 32.w, top: 24.w), + width: 140, + height: 150, + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fill, + image: AssetImage( + R.ASSETS_IMAGES_CARD_YELLOW_PNG), + )), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '访客邀请', + style: TextStyle( + color: Color(0xD9000000), + fontSize: 26.sp, + fontWeight: FontWeight.bold), + ), + 10.hb, + Text( + '一键分享', + style: TextStyle( + color: Color(0x73000000), + fontSize: 20.sp, ), - 10.hb, - Text( - '提交报警位置给物业', - style: TextStyle( - color: Color(0x73000000), - fontSize: 20.sp, - ), + ), + Text( + '让拜访不再是难事', + style: TextStyle( + color: Color(0x73000000), + fontSize: 20.sp, ), - ], - ), - Spacer(), - Image.asset( - R.ASSETS_ICONS_ICON_MAIN_POLICE_PNG, - width: 98.w, - height: 98.w, - ), - 20.wb, - ], + ), + Spacer(), + Image.asset( + R.ASSETS_ICONS_ICON_MAIN_INVITE_PNG, + width: 100.w, + height: 100.w, + ), + 30.hb, + ], + ), ), + onTap: () { + Get.to(VisitorAccessPage()); + }, ), - onTap: () { - Get.to(AlarmPage()); - }, - ), - GestureDetector( - child: Container( - margin: EdgeInsets.only(top: 20.w), - width: 190, - height: 69, - decoration: BoxDecoration( - image: DecorationImage( - fit: BoxFit.fill, - image: - AssetImage(R.ASSETS_IMAGES_CARD_BLUE_PNG), - )), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, + 25.wb, + Container( + margin: EdgeInsets.only(top: 24.w), + child: Column( children: [ - 20.wb, - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - 20.hb, - Text( - '建议咨询', - style: TextStyle( - color: Color(0xD9000000), - fontSize: 26.sp, - fontWeight: FontWeight.bold), + GestureDetector( + child: Container( + width: 190, + height: 69, + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fill, + image: AssetImage( + R.ASSETS_IMAGES_CARD_PINK_PNG), + )), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + 20.wb, + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + 20.hb, + Text( + '一键报警', + style: TextStyle( + color: Color(0xD9000000), + fontSize: 26.sp, + fontWeight: + FontWeight.bold), + ), + 10.hb, + Text( + '提交报警位置给物业', + style: TextStyle( + color: Color(0x73000000), + fontSize: 20.sp, + ), + ), + ], + ), + Spacer(), + Image.asset( + R.ASSETS_ICONS_ICON_MAIN_POLICE_PNG, + width: 98.w, + height: 98.w, + ), + 20.wb, + ], ), - 10.hb, - Text( - '欢迎给我们提供服务意见', - style: TextStyle( - color: Color(0x73000000), - fontSize: 20.sp, - ), - ), - ], - ), - Spacer(), - Image.asset( - R.ASSETS_ICONS_ICON_MAIN_CONSULT_PNG, - width: 98.w, - height: 98.w, + ), + onTap: () { + Get.to(AlarmPage()); + }, ), - 20.wb, + GestureDetector( + child: Container( + margin: EdgeInsets.only(top: 20.w), + width: 190, + height: 69, + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fill, + image: AssetImage( + R.ASSETS_IMAGES_CARD_BLUE_PNG), + )), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + 20.wb, + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + 20.hb, + Text( + '建议咨询', + style: TextStyle( + color: Color(0xD9000000), + fontSize: 26.sp, + fontWeight: + FontWeight.bold), + ), + 10.hb, + Text( + '欢迎给我们提供服务意见', + style: TextStyle( + color: Color(0x73000000), + fontSize: 20.sp, + ), + ), + ], + ), + Spacer(), + Image.asset( + R.ASSETS_ICONS_ICON_MAIN_CONSULT_PNG, + width: 98.w, + height: 98.w, + ), + 20.wb, + ], + ), + ), + onTap: () { + Get.to(AdvicePage( + type: AdviceType.SUGGESTION)); + }, + ) ], ), - ), - onTap: () { - Get.to(AdvicePage(type: AdviceType.SUGGESTION)); - }, - ) - ], + ) + ], + ), ), - ) - ], + SliverToBoxAdapter( + child: Column( + children: [ + HomeTitle( + title: '社区活动', + suffixTitle: '查看全部', + onTap: () => Get.to(() => ActivityListPage()), + ), + _activityItemModels == [] + ? SizedBox() + : Container( + height: 400.w, + padding: EdgeInsets.only(left: 32.w), + child: ListView.separated( + padding: EdgeInsets.zero, + separatorBuilder: (context, index) { + return SizedBox( + width: 16.w, + ); + }, + scrollDirection: Axis.horizontal, + itemBuilder: (context, index) { + return Container( + width: 500.w, + child: Builder( + builder: (context) { + return ActivityCard( + model: _activityItemModels[ + index]); + }, + ), + ); + }, + itemCount: _activityItemModels.length, + ), + ), + // : ActivityCard(model: _activityItemModel) + // .pSymmetric(h: 24.w, v: 24.w), + ], + )), + ], + ), ), ), - SliverToBoxAdapter( - child: Column( - children: [ - // HomeTitle( - // title: '公共资讯', - // suffixTitle: '更多资讯', - // onTap: () async { - // final cancel = BotToast.showLoading(); - // BaseModel model = await NetUtil().get(API.news.category); - // List? category; - // if (model.status == true && model.data != null) { - // category = (model.data as List) - // .map((e) => NewsCategoryModel.fromJson(e)) - // .toList(); - // } - // cancel(); - // Get.to( - // () => PublicInfomationPage(models: category ?? [])); - // }, - // ), - HomeTitle( - title: '社区活动', - suffixTitle: '查看全部', - onTap: () => Get.to(() => ActivityListPage()), - ), - _activityItemModels == [] - ? SizedBox() - : Container( - height: 400.w, - padding: EdgeInsets.only(left: 32.w), - child: ListView.separated( - padding: EdgeInsets.zero, - separatorBuilder: (context, index) { - return SizedBox( - width: 16.w, - ); - }, - scrollDirection: Axis.horizontal, - itemBuilder: (context, index) { - return Container( - width: 500.w, - child: Builder( - builder: (context) { - return ActivityCard( - model: _activityItemModels[index]); - }, - ), - ); - }, - itemCount: _activityItemModels.length, - ), - ), - // : ActivityCard(model: _activityItemModel) - // .pSymmetric(h: 24.w, v: 24.w), - ], - )), ], ), - ), - OverlayLivingBtnWidget() - ], + OverlayLivingBtnWidget() + ], + ), ), ); } @@ -447,10 +481,25 @@ class _HomePageState extends State return Container( width: double.infinity, height: 320.w, + decoration: + BoxDecoration(border: Border.all(width: 0, color: _barColor.value)), child: AspectRatio( aspectRatio: 375 / 160, child: Swiper( key: UniqueKey(), + onIndexChanged: (index) async { + if (_swiperModels.isNotEmpty) { + var color = await PaletteGenerator.fromImageProvider( + CachedNetworkImageProvider( + API.image( + ImgModel.first(_swiperModels[index].voResourcesImgList)), + )); + _barColor.value = + color.dominantColor?.color ?? Colors.transparent; + } else { + _barColor.value = Colors.transparent; + } + }, itemBuilder: (BuildContext context, int index) { return getSwiperImage(_swiperModels[index]); }, @@ -562,3 +611,62 @@ class _HomePageState extends State @override bool get wantKeepAlive => true; } + +class BeeBallPauseHeader extends Header { + /// Key + final Key? key; + + final ValueNotifier bgColor; + + final LinkHeaderNotifier linkNotifier = LinkHeaderNotifier(); + + BeeBallPauseHeader({ + this.key, + required this.bgColor, + bool enableHapticFeedback = true, + bool enableInfiniteRefresh = false, + }) : super( + extent: 70.0, + triggerDistance: 70.0, + float: false, + enableHapticFeedback: enableHapticFeedback, + enableInfiniteRefresh: enableInfiniteRefresh, + ); + + @override + Widget contentBuilder( + BuildContext context, + RefreshMode refreshState, + double pulledExtent, + double refreshTriggerPullDistance, + double refreshIndicatorExtent, + AxisDirection axisDirection, + bool float, + Duration? completeDuration, + bool enableInfiniteRefresh, + bool success, + bool noMore) { + linkNotifier.contentBuilder( + context, + refreshState, + pulledExtent, + refreshTriggerPullDistance, + refreshIndicatorExtent, + axisDirection, + float, + completeDuration, + enableInfiniteRefresh, + success, + noMore); + return ValueListenableBuilder( + valueListenable: bgColor, + builder: (context, Color color, child) { + return BallPulseHeaderWidget( + key: key, + color: color.withBlue(128), + backgroundColor: color, + linkNotifier: linkNotifier, + ); + }); + } +} diff --git a/lib/pages/home/widget/animate_app_bar.dart b/lib/pages/home/widget/animate_app_bar.dart index 13e7d18f..e3d997e7 100644 --- a/lib/pages/home/widget/animate_app_bar.dart +++ b/lib/pages/home/widget/animate_app_bar.dart @@ -1,14 +1,17 @@ import 'package:aku_new_community/provider/app_provider.dart'; import 'package:aku_new_community/utils/headers.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:provider/provider.dart'; class AnimateAppBar extends StatefulWidget with PreferredSizeWidget { final ScrollController? scrollController; final List? actions; + final ValueNotifier bgColor; - AnimateAppBar({Key? key, this.scrollController, this.actions}) + AnimateAppBar( + {Key? key, this.scrollController, this.actions, required this.bgColor}) : super(key: key); @override @@ -19,63 +22,57 @@ class AnimateAppBar extends StatefulWidget with PreferredSizeWidget { } class _AnimateAppBarState extends State { - Color _bgColor = Colors.white; - @override void initState() { super.initState(); - widget.scrollController!.addListener(() { - setState(() { - _bgColor = widget.scrollController!.offset > 30 - ? Colors.white - : widget.scrollController!.offset < 0 - ? Colors.transparent - : Colors.white - .withOpacity((widget.scrollController!.offset / 30)); - }); - }); } @override Widget build(BuildContext context) { final appProvider = Provider.of(context); - return Padding( - padding: const EdgeInsets.only(top: 5), - child: AppBar( - titleSpacing: 10.0, - title: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (appProvider.location != null) - Padding( - padding: const EdgeInsets.only(right: 5), - child: Image.asset( - R.ASSETS_ICONS_ICON_MAIN_LOCATION_PNG, - width: 32.w, - height: 32.w, - ), - ), - Text( - appProvider.location?['city'] == null - ? '' - : appProvider.location?['city'] as String? ?? '', - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 24.sp, - color: Color(0xff333333), + return ValueListenableBuilder( + valueListenable: widget.bgColor, + builder: (context, color, child) { + return AppBar( + systemOverlayStyle: SystemUiOverlayStyle( + statusBarColor: widget.bgColor.value, + statusBarIconBrightness: Brightness.light), + titleSpacing: 10.0, + title: child, + backgroundColor: widget.bgColor.value, + actions: widget.actions, + ); + }, + child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ + if (appProvider.location != null) + Padding( + padding: const EdgeInsets.only(right: 5), + child: Image.asset( + R.ASSETS_ICONS_ICON_MAIN_LOCATION_PNG, + width: 32.w, + height: 32.w, ), - textAlign: TextAlign.center, ), - Text( - '(${appProvider.weatherType} ${appProvider.weatherTemp}℃)', - style: TextStyle( - fontSize: 24.sp, - color: Color(0xff999999), - ), - textAlign: TextAlign.center, + Text( + appProvider.location?['city'] == null + ? '' + : appProvider.location?['city'] as String? ?? '', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 24.sp, + color: Color(0xff333333), + ), + textAlign: TextAlign.center, + ), + Text( + '(${appProvider.weatherType} ${appProvider.weatherTemp}℃)', + style: TextStyle( + fontSize: 24.sp, + color: Color(0xff999999), ), - ]), - backgroundColor: _bgColor, - actions: widget.actions, - ), + textAlign: TextAlign.center, + ), + ]), ); } } diff --git a/lib/pages/home/widget/filter_tool_bar.dart b/lib/pages/home/widget/filter_tool_bar.dart deleted file mode 100644 index d7199f2c..00000000 --- a/lib/pages/home/widget/filter_tool_bar.dart +++ /dev/null @@ -1,592 +0,0 @@ -/* - * ==================================================== - * package : widgets - * author : Created by nansi. - * time : 2019/5/13 1:44 PM - * remark : - * ==================================================== - */ - -import 'package:aku_new_community/utils/text_utils.dart'; -import 'package:flutter/material.dart'; - -/// 自筛选列表点击监听 -typedef SelectedListener = Function(int selectedIndex, FilterItemModel item); - -/// 下拉列表状态变更 -typedef PopOptionHandle = Function(OptionListStatus status); - -/// filterBar 标题点击、变更等监听 -typedef FilterToolBarListener = Function(bool update); - -class FilterToolBarController { - late FilterResultContainerHelper helper; - late int selectedIndex; - late FilterItemModel item; - late GlobalKey _containerKey; - late GlobalKey _toolBarKey; - - /// [update] 是否需要通知外层 sublist 点击的index 和上次一致时,不通知外层 - FilterToolBarListener updateToolBarState = (bool update) {}; - - close() { - helper.changeOptionListStatus(OptionListStatus.close); - } - - get toolBarDx { - RenderBox box = _toolBarKey.currentContext?.findRenderObject() - as RenderBox; //_toolBarKey.currentContext.findRenderObject(); - Offset offset = box.localToGlobal(Offset.zero); - return offset.dx; - } - - double get toolBarDy { - /// toolbar 距离top 的间距 - container外层距离top的间距 - RenderBox containerBox = - _containerKey.currentContext?.findRenderObject() as RenderBox; - RenderBox box = _toolBarKey.currentContext?.findRenderObject() as RenderBox; - Offset containerTopOffset = containerBox.localToGlobal(Offset.zero); - Offset toolBarTopOffset = box.localToGlobal(Offset.zero); - return toolBarTopOffset.dy - containerTopOffset.dy; - } - -////获取position -// RenderBox box = _key.currentContext.findRenderObject(); -// Offset offset = box.localToGlobal(Offset.zero); -// -////获取size -// Size size = box.size; - -// print(" ---- $offset ------- $size"); - -} - -enum OptionListStatus { open, close } - -/// 筛选子列表操作 -class FilterResultContainerHelper { - final PopOptionHandle handle; - - /// 字筛选列表弹出状态 - late OptionListStatus status; - - FilterResultContainerHelper({required this.handle}); - - changeOptionListStatus(OptionListStatus status) { - this.status = status; - this.handle(status); - } -} - -/// 筛选下拉列表容器 与 FilterToolBar 一起使用 -class FilterToolBarResultContainer extends StatefulWidget { - final FilterToolBarController? controller; - final Widget? body; - - const FilterToolBarResultContainer( - {GlobalKey? key, this.controller, this.body}) - : assert(controller != null, "controller 不为空"); - - @override - State createState() { - return _FilterToolBarResultContainerState(); - } -} - -class _FilterToolBarResultContainerState - extends State with TickerProviderStateMixin { - /// 子列表行数 - late int _lines; - - int maxLines = 3; - - /// 子列表单行高度 - double _lineHeight = 35.0; - - /// 底部内边距 - double _bottomSpacing = 8.0; - - /// 顶部边距 - double _topSpacing = 8.0; - - /// 未选中颜色 - Color _unselectedColor = Colors.grey[700]!; - - /// toolbar 字体大小 - // double _toolBarTitleFont = 14.0; - - /// 子列表字体大小 - double _subTitleFont = 13.0; - - /// 子列表单行内边距 因为点击要整行选中,所以在row上设置左右边距 - EdgeInsetsGeometry _subtitleRowPadding = EdgeInsets.only(left: 15, right: 15); - - late AnimationController _animationController; - late Animation _animation; - - @override - void initState() { - _animationController = - AnimationController(vsync: this, duration: Duration(milliseconds: 150)); - - _lines = maxLines; - - widget.controller?.helper = FilterResultContainerHelper(handle: (status) { - if (status == OptionListStatus.open) { - _buildAnimation(widget.controller!.item); - _animationController.forward(); - } else { - _animationController.reset(); - } - }); - - if (widget.key == null) { - widget.controller!._containerKey = GlobalKey(); - } else { - widget.controller!._containerKey = widget.key as GlobalKey; - } - - super.initState(); - } - - @override - void dispose() { - _animationController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Container( - key: widget.controller!._containerKey, - child: _buildBody(context), - ); - } - - Stack _buildBody(BuildContext context) { - return Stack( - children: [ - /// body内容 - Container( - height: double.infinity, - child: widget.body, - ), - - /// 蒙版 - _maskView(), - - widget.controller?._toolBarKey == null - ? Container() - : Positioned( - top: widget.controller!.toolBarDy + 40, - left: 0, - right: 0, - bottom: 0, - child: Stack(children: [ - widget.controller!.item.type == FilterItemType.list - ? _buildList(context) - : Container(), - ])) - ], - ); - } - - Widget _maskView() { - double? num = widget.controller?.toolBarDy; - - return widget.controller?._toolBarKey == null - ? Container() - : Positioned( - top: (num as double) + 40, - left: 0, - right: 0, - bottom: 0, - child: Offstage( - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - widget.controller!.helper.changeOptionListStatus( - OptionListStatus.close, - ); - widget.controller!.updateToolBarState(false); - _animationController.reset(); - }, - child: Opacity( - opacity: 0.3, - child: Container( - color: Colors.black, - ), - ), - ), - offstage: _animation == null || - (_animation.status == AnimationStatus.dismissed), - ), - ); - } - - /// 有多个子列表时 因为有设置最大行数,小于最大行数[widget.maxLines]时,以子列表个数为准, - /// 否则以最大行数为准,选中时切换动画, - _buildAnimation(FilterItemModel item) { - _lines = - item.subtitles!.length > maxLines ? maxLines : item.subtitles!.length; - - _animation = new Tween( - begin: 0.0 - _lines * _lineHeight - _bottomSpacing - _topSpacing, - end: 0.0) - .animate(_animationController) - ..addListener(() { - setState(() { - // the state that has changed here is the animation object’s value - }); - }); - } - - /// 筛选子列表 - Positioned _buildList(context) { - FilterItemModel item = widget.controller!.item; - return Positioned( - top: _animation.value, - left: 0, - right: 0, - child: LimitedBox( - maxHeight: _lineHeight * _lines + _topSpacing + _bottomSpacing, - child: Container( - padding: EdgeInsets.only(bottom: _bottomSpacing, top: 5), - height: _lineHeight * item.subtitles!.length + - _bottomSpacing + - _topSpacing, - decoration: BoxDecoration( - color: Color.fromARGB(240, 255, 255, 255), - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(10), - bottomRight: Radius.circular(10))), - child: MediaQuery.removePadding( - context: context, - removeTop: true, - child: ListView.builder( - physics: NeverScrollableScrollPhysics(), - controller: PrimaryScrollController.of(context), - itemCount: item.subtitles!.length, - itemBuilder: (context, index) { - bool subTitleSelected = item.selectedSubIndex == index; - return Container( - height: _lineHeight, - child: RawMaterialButton( - onPressed: () { - widget.controller!.helper - .changeOptionListStatus(OptionListStatus.close); - widget.controller!.updateToolBarState(false); - if (item.selectedSubIndex == index) return; - - item.selectedSubIndex = index; - String title = item.subtitleShort == null || - TextUtils.isEmpty(item.subtitleShort![index]) - ? item.subtitles![index] - : item.subtitleShort![index]; - item.title = title; - - widget.controller!.updateToolBarState(true); - }, - child: _sublistItem(index, item, subTitleSelected), - ), - ); - }), - ), - ), - ), - ); - } - - /// 子列表item - Container _sublistItem( - int index, FilterItemModel item, bool subTitleSelected) { - return Container( - padding: _subtitleRowPadding, - child: Row( - children: [ - Offstage( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 8), - child: Icon( - Icons.check, - size: 17, - color: Colors.red, - ), - ), - offstage: index != item.selectedSubIndex, - ), - Expanded( - child: Text( - item.subtitles![index], - style: TextStyle( - fontSize: _subTitleFont, - color: _unselectedColor, - fontWeight: - (subTitleSelected ? FontWeight.w600 : FontWeight.w400)), - )), - ], - ), - ); - } -} - -class FilterToolBar extends StatefulWidget { - FilterToolBar({ - required this.titles, - required this.listener, - required this.controller, - this.selectedColor, - this.maxLines = 4, - this.trialing, - this.startWidget, - this.fontSize = 15.0, - this.height = 40, - }) : assert(listener != null, "请设置监听事件"), - assert(controller != null, "请设置controller"); - - final List titles; - final Color? selectedColor; - final int maxLines; - final SelectedListener listener; - final Widget? trialing; - final Widget? startWidget; - final FilterToolBarController? controller; - final double fontSize; - final double height; - - @override - State createState() { - return _FilterToolBarState(); - } -} - -class _FilterToolBarState extends State - with TickerProviderStateMixin { - Color _unselectedColor = Colors.grey[700]!; - - GlobalKey _key = GlobalKey(); - - @override - void initState() { - super.initState(); - - widget.controller?.selectedIndex = widget.controller?.selectedIndex ?? 0; - - widget.controller?._toolBarKey = _key; - - widget.controller?.updateToolBarState = (bool update) { -// print("----- ${widget.controller.selectedIndex}"); - if (update) { - widget.listener( - widget.controller!.selectedIndex, widget.controller!.item); - } - setState(() {}); - }; - } - - @override - Widget build(BuildContext context) { - return Container( - width: double.infinity, - height: widget.height, - child: _buildToolBar(), - ); - } - - Container _buildToolBar() { - List items = []; - if (widget.startWidget != null) { - items.add(SizedBox( - width: 60, - )); - items.add(widget.startWidget!); - items.add(SizedBox( - width: 20, - )); - } - items.addAll(_buildToolBarItem()); - if (widget.trialing != null) { - items.add(widget.trialing!); - } - - return Container( - key: _key, - height: 40, - decoration: BoxDecoration( - color: Colors.white, - border: Border( - top: BorderSide(color: Colors.grey[200]!, width: 0.5), - bottom: BorderSide(color: Colors.grey[200]!, width: 0.5))), - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: items, - ), - ); - } - - List _buildToolBarItem() { - return widget.titles.map((item) { - int index = widget.titles.indexOf(item); - bool selected = index == widget.controller?.selectedIndex; - Color color = (selected ? widget.selectedColor : _unselectedColor)!; - return Expanded( - child: GestureDetector( - onTap: () { - widget.controller?.item = item; - - /// 列表弹出后直接点击toolbar上按钮 列表消失 - if (widget.controller?.helper != null && - widget.controller?.helper.status == OptionListStatus.open) { - widget.controller?.helper.changeOptionListStatus( - OptionListStatus.close, - ); - } else { - if (item.type == FilterItemType.list) { - /// 当前已选中,再次点击弹出列表 - if (widget.controller?.selectedIndex == index) { - if (widget.controller?.helper != null) { - widget.controller?.helper.changeOptionListStatus( - OptionListStatus.open, - ); - } else { - FlutterError("列表类型需要与 FilterToolBarResultContainer 一起使用"); - } - } else { - /// 点击其他列表项时,把当前列表项之前选中的状态返回 - widget.listener(index, item); - } - } - } - - /// 上下箭头选项点击 - if (item.type == FilterItemType.double) { - if (widget.controller?.selectedIndex != index) { - item.selectedList![index] = true; - item.topSelected = item.selectedList![index]; - } else { - //print(item.topSelected); - //item.topSelected = !item.topSelected; - // print(widget.titles[index].topSelected); - item.selectedList![index] = !item.selectedList![index]; - item.topSelected = item.selectedList![index]; - } - widget.listener(index, item); - } - - /// 普通 - else if (item.type == FilterItemType.normal) { - if (widget.controller?.selectedIndex == index) return; - widget.listener(index, item); - } - - widget.controller?.selectedIndex = index; - - setState(() {}); - }, - child: Container( - color: Colors.white, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(item.title, - style: TextStyle( - fontSize: widget.fontSize, - color: color, - fontWeight: FontWeight.w400) - // AppTextStyle.generate(widget.fontSize, - // color: color, fontWeight: FontWeight.w400), - ), - _buildArrow(item, color, selected, index) - ], - ), - ), - ), - ); - }).toList(); - } - - _buildArrow(FilterItemModel item, color, bool selected, int index) { - if (item.type == FilterItemType.list) { - return Icon( - selected - ? (widget.controller?.helper != null && - widget.controller?.helper.status == OptionListStatus.open - ? Icons.arrow_drop_up - : Icons.arrow_drop_down) - : Icons.arrow_drop_down, - color: color, - size: 19, - ); - } else if (item.type == FilterItemType.double) { - if (selected) { - return Padding( - padding: const EdgeInsets.only(left: 2.0), - child: Icon( - item.selectedList![index] - ? IconData(0xe620, fontFamily: "AppIcons") - : IconData(0xe621, fontFamily: "AppIcons"), - size: 7, - color: color, - ), - ); - } else { - return Padding( - padding: const EdgeInsets.only(left: 2.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - IconData(0xe620, fontFamily: "AppIcons"), - size: 7, - color: _unselectedColor, - ), - Icon( - IconData(0xe621, fontFamily: "AppIcons"), - size: 7, - color: _unselectedColor, - ), - ], - ), - ); - } - } else { - return Container(); - } - } -} - -enum FilterItemType { - /// 列表形式 - list, - - /// 价格等上下箭头 - double, - - /// 普通 - normal -} - -class FilterItemModel { - final FilterItemType type; - String title; - final List? subtitles; - - /// 列表下拉时的子标题 - final List? subtitleShort; - List? selectedList; - bool topSelected; - int selectedSubIndex = 0; - - FilterItemModel({ - required this.type, - required this.title, - this.selectedList, - this.subtitles, - this.subtitleShort, - this.topSelected = true, - }) : assert( - type == FilterItemType.list - ? (subtitles != null && subtitles.length > 0) - : true, - "type为list,列表项不能为空"); -} diff --git a/lib/pages/home/widget/home_search.dart b/lib/pages/home/widget/home_search.dart deleted file mode 100644 index 4cb5bbf7..00000000 --- a/lib/pages/home/widget/home_search.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:aku_new_community/utils/headers.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -class HomeSearch extends StatefulWidget { - HomeSearch({Key? key}) : super(key: key); - - @override - _HomeSearchState createState() => _HomeSearchState(); -} - -class _HomeSearchState extends State { - @override - Widget build(BuildContext context) { - return Container( - // decoration: BoxDecoration( - // gradient: LinearGradient( - // begin: Alignment.centerLeft, - // end: Alignment.centerRight, - // colors: [Color(0xffffd000), Color(0xffffbd00)], - // ), - // ), - color: Colors.white, - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top, - left: 32.w, - right: 32.w, - bottom: 16.w, - ), - // child: MaterialButton( - // materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - // height: 72.w, - // shape: StadiumBorder(), - // elevation: 0, - // minWidth: double.infinity, - // color: Color(0xFFF3F3F3), - // onPressed: () { - // Get.to(() => BeeSearch()); - // }, - // child: Row( - // children: [ - // Icon( - // Icons.search, - // size: 32.w, - // color: Color(0xFF666666), - // ), - // 10.wb, - // '搜索应用'.text.size(28.sp).color(ktextSubColor).make().expand(), - // ], - // ), - // ), - ); - } -} diff --git a/lib/ui/community/activity/activity_card.dart b/lib/ui/community/activity/activity_card.dart index f5e0267b..8b59491f 100644 --- a/lib/ui/community/activity/activity_card.dart +++ b/lib/ui/community/activity/activity_card.dart @@ -28,9 +28,9 @@ class ActivityCard extends StatelessWidget { elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24.w), - side: BorderSide( - color: Colors.grey, - ), + // side: BorderSide( + // color: Colors.grey, + // ), ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, child: Column( @@ -77,12 +77,18 @@ class ActivityCard extends StatelessWidget { height: 39.w, width: 98.w, decoration: BoxDecoration( - color: outdate ? Color(0xFFABABAB) : Color(0x80FEBF76), + color: outdate + ? Colors.black.withOpacity(0.06) + : Color(0x80FEBF76), borderRadius: BorderRadius.all(Radius.circular(4)), ), child: outdate - ? '已结束'.text.size(22.sp).color(Color(0xFF666666)).make() + ? '已结束' + .text + .size(22.sp) + .color(Colors.black.withOpacity(0.25)) + .make() : '报名中' .text .size(22.sp) diff --git a/pubspec.lock b/pubspec.lock index fdc06e5a..43116429 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -814,6 +814,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.3" + palette_generator: + dependency: "direct main" + description: + name: palette_generator + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.2" path: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index fe91a73c..b684e7ba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -109,6 +109,8 @@ dependencies: carousel_slider: ^4.0.0-nullsafety.0 #跳转索引列表 scroll_to_index: ^2.1.1 + #提取图片主色 + palette_generator: ^0.3.2 dev_dependencies: