diff --git a/lib/common/values/view_mode.dart b/lib/common/values/view_mode.dart index 4da2a3a..d7356de 100644 --- a/lib/common/values/view_mode.dart +++ b/lib/common/values/view_mode.dart @@ -1 +1,11 @@ -enum ViewMode { list, calendar } +enum ViewModeType { + list(0, 'ListView'), + calendar(1, 'CalendarView'); + + const ViewModeType(this.number, this.value); + + final int number; + final String value; + + static ViewModeType getType(int number) => ViewModeType.values.firstWhere((e) => e.number == number); +} diff --git a/lib/components/home_tab_view/home_tab_view_view.dart b/lib/components/home_tab_view/home_tab_view_view.dart index 793916b..76d6301 100644 --- a/lib/components/home_tab_view/home_tab_view_view.dart +++ b/lib/components/home_tab_view/home_tab_view_view.dart @@ -21,7 +21,6 @@ class HomeTabViewComponent extends StatelessWidget { return MasonryGridView.builder( gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 440), padding: const EdgeInsets.symmetric(horizontal: 4.0), - shrinkWrap: true, itemBuilder: (context, index) { final aspect = state.diaryList.value[index].aspect; //如果是横图,显示大卡片,竖图或者没有图显示小卡片 diff --git a/lib/pages/home/home_logic.dart b/lib/pages/home/home_logic.dart index 85aeb24..86b8ec5 100644 --- a/lib/pages/home/home_logic.dart +++ b/lib/pages/home/home_logic.dart @@ -35,12 +35,10 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin { void onReady() { // TODO: implement onReady - var innerController = state.nestedScrollKey.currentState!.innerController; - - innerController.addListener(() async { + state.innerController.addListener(() async { if (!tabController.indexIsChanging) { - double offset = innerController.offset; - double maxScrollExtent = innerController.position.maxScrollExtent; + double offset = state.innerController.offset; + double maxScrollExtent = state.innerController.position.maxScrollExtent; // 显示或隐藏“回到顶部”按钮 state.isToTopShow.value = offset > 0; // 分页加载 @@ -51,8 +49,6 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin { } } }); - - initTabListener(); super.onReady(); } @@ -64,23 +60,9 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin { super.onClose(); } - void initTabListener() { - //监听tab滚动,切换时回到顶部 - - tabController.addListener(() async { - if (!tabController.indexIsChanging) { - var outerController = state.nestedScrollKey.currentState!.outerController; - if (outerController.offset != .0) { - await outerController.animateTo(0.0, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut); - //标记为变化结束 - } - } - }); - } - Future toTop() async { - var outerController = state.nestedScrollKey.currentState!.outerController; - await outerController.animateTo(0.0, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut); + await state.innerController.animateTo(0.0, duration: const Duration(milliseconds: 100), curve: Curves.easeInOut); + await state.outerController.animateTo(0.0, duration: const Duration(milliseconds: 100), curve: Curves.easeInOut); } //初始化分类tab @@ -101,11 +83,7 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin { if (state.categoryList.length < currentIndex) { currentIndex = state.categoryList.length; } - //移出原有监听器 - tabController.removeListener(initTabListener); tabController = TabController(length: state.categoryList.length + 1, vsync: this, initialIndex: currentIndex); - //重新开始监听 - initTabListener(); maxScrollExtentSet = {}; //添加帧回调保证对应logic已经被创建 WidgetsBinding.instance.addPostFrameCallback((_) async { @@ -147,9 +125,9 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin { } //切换视图模式 - Future changeViewMode(ViewMode viewMode) async { - state.viewMode.value = viewMode.name; - await Utils().prefUtil.setValue('homeViewMode', viewMode.name); + Future changeViewMode(ViewModeType viewModeType) async { + state.viewModeType.value = viewModeType; + await Utils().prefUtil.setValue('homeViewMode', viewModeType.number); } //新增一篇日记 @@ -161,6 +139,5 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin { fabAnimationController.reset(); state.isFabExpanded.value = false; await updateDiary(); - //点击添加按钮后新增一篇日记 } } diff --git a/lib/pages/home/home_state.dart b/lib/pages/home/home_state.dart index e2dd660..995087c 100644 --- a/lib/pages/home/home_state.dart +++ b/lib/pages/home/home_state.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:mood_diary/common/models/isar/category.dart'; +import 'package:mood_diary/common/values/view_mode.dart'; import 'package:mood_diary/utils/utils.dart'; class HomeState { @@ -13,8 +14,12 @@ class HomeState { //主滚动列表key late GlobalKey nestedScrollKey; + ScrollController get innerController => nestedScrollKey.currentState!.innerController; + + ScrollController get outerController => nestedScrollKey.currentState!.outerController; + //视图模式状态 - late RxString viewMode; + late Rx viewModeType; //fab展开状态 late RxBool isFabExpanded; @@ -28,7 +33,7 @@ class HomeState { HomeState() { isFabExpanded = false.obs; isToTopShow = false.obs; - viewMode = Utils().prefUtil.getValue('homeViewMode')!.obs; + viewModeType = ViewModeType.getType(Utils().prefUtil.getValue('homeViewMode')!).obs; selectDateTime = [].obs; categoryList = Utils().isarUtil.getAllCategory().obs; customTitleName = Utils().prefUtil.getValue('customTitleName')!; diff --git a/lib/pages/home/home_view.dart b/lib/pages/home/home_view.dart index a553321..1e5f86b 100644 --- a/lib/pages/home/home_view.dart +++ b/lib/pages/home/home_view.dart @@ -54,10 +54,19 @@ class HomePage extends StatelessWidget { ); }); return TabBarView( - controller: logic.tabController, - physics: const NeverScrollableScrollPhysics(), - children: allView, - ); + controller: logic.tabController, physics: const NeverScrollableScrollPhysics(), children: allView); + } + + Widget buildModal() { + return AnimatedBuilder( + animation: logic.fabAnimation, + builder: (context, child) { + return state.isFabExpanded.value + ? ModalBarrier( + color: Color.lerp(Colors.transparent, Colors.black54, logic.fabAnimation.value), + ) + : const SizedBox.shrink(); + }); } return GetBuilder( @@ -67,109 +76,102 @@ class HomePage extends StatelessWidget { return Scaffold( drawer: const SideBarComponent(), drawerEnableOpenDragGesture: false, - body: Obx(() { - return Stack( - children: [ - NestedScrollView( - key: state.nestedScrollKey, - headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { - return [ - SliverAppBar( - title: Tooltip( - message: '侧边栏', - child: InkWell( - onTap: () { - Scaffold.of(context).openDrawer(); - }, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: Text( - state.customTitleName.isNotEmpty ? state.customTitleName : i18n.appName, - overflow: TextOverflow.ellipsis, - ), + body: Stack( + children: [ + NestedScrollView( + key: state.nestedScrollKey, + headerSliverBuilder: (context, _) { + return [ + SliverAppBar( + title: Tooltip( + message: '侧边栏', + child: InkWell( + onTap: () { + Scaffold.of(context).openDrawer(); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Text( + state.customTitleName.isNotEmpty ? state.customTitleName : i18n.appName, + overflow: TextOverflow.ellipsis, ), - const Icon(Icons.chevron_right) - ], - ), + ), + const Icon(Icons.chevron_right) + ], ), ), - automaticallyImplyLeading: false, - actions: [ - IconButton( - onPressed: () { - showModalBottomSheet( - context: context, - showDragHandle: true, - useSafeArea: true, - builder: (context) { - return const SearchSheetComponent(); - }); - }, - icon: const Icon(Icons.search), - tooltip: '搜索', - ), - PopupMenuButton( - offset: const Offset(0, 46), - tooltip: '更多', - itemBuilder: (context) { - return >[ - CheckedPopupMenuItem( - checked: state.viewMode.value == ViewMode.list.name, - onTap: () async { - await logic.changeViewMode(ViewMode.list); - }, - child: Text(i18n.homeViewModeList), - ), - CheckedPopupMenuItem( - checked: state.viewMode.value == ViewMode.calendar.name, - onTap: () async { - await logic.changeViewMode(ViewMode.calendar); - }, - child: Text(i18n.homeViewModeCalendar), - ), - ]; - }, - ), - ], - bottom: PreferredSize( - preferredSize: const Size.fromHeight(46.0), - child: Align( - alignment: Alignment.centerLeft, - child: TabBar( - controller: logic.tabController, - isScrollable: true, - dividerHeight: .0, - tabAlignment: TabAlignment.start, - indicatorSize: TabBarIndicatorSize.tab, - splashFactory: NoSplash.splashFactory, - indicator: - ShapeDecoration(shape: const StadiumBorder(), color: colorScheme.secondaryContainer), - indicatorWeight: .0, - indicatorPadding: const EdgeInsets.all(8.0), - tabs: buildTabBar(), - ), + ), + automaticallyImplyLeading: false, + actions: [ + IconButton( + onPressed: () { + showModalBottomSheet( + context: context, + showDragHandle: true, + useSafeArea: true, + builder: (context) { + return const SearchSheetComponent(); + }); + }, + icon: const Icon(Icons.search), + tooltip: '搜索', + ), + PopupMenuButton( + offset: const Offset(0, 46), + tooltip: '更多', + itemBuilder: (context) { + return >[ + CheckedPopupMenuItem( + checked: state.viewModeType.value == ViewModeType.list, + onTap: () async { + await logic.changeViewMode(ViewModeType.list); + }, + child: Text(i18n.homeViewModeList), + ), + CheckedPopupMenuItem( + checked: state.viewModeType.value == ViewModeType.calendar, + onTap: () async { + await logic.changeViewMode(ViewModeType.calendar); + }, + child: Text(i18n.homeViewModeCalendar), + ), + ]; + }, + ), + ], + bottom: PreferredSize( + preferredSize: const Size.fromHeight(46.0), + child: Align( + alignment: Alignment.centerLeft, + child: TabBar( + controller: logic.tabController, + isScrollable: true, + dividerHeight: .0, + tabAlignment: TabAlignment.start, + indicatorSize: TabBarIndicatorSize.tab, + splashFactory: NoSplash.splashFactory, + indicator: + ShapeDecoration(shape: const StadiumBorder(), color: colorScheme.secondaryContainer), + indicatorWeight: .0, + indicatorPadding: const EdgeInsets.all(8.0), + tabs: buildTabBar(), ), ), ), - ]; - }, - body: state.viewMode.value == ViewMode.list.name ? buildListView() : buildDatePicker(), - ), - //如果fab打开了,显示一个蒙层 - if (state.isFabExpanded.value) ...[ - AnimatedBuilder( - animation: logic.fabAnimation, - builder: (context, child) { - return ModalBarrier( - color: Color.lerp(Colors.transparent, Colors.black54, logic.fabAnimation.value), - ); - }) - ] - ], - ); - }), + ) + ]; + }, + body: switch (state.viewModeType.value) { + ViewModeType.list => buildListView(), + ViewModeType.calendar => buildDatePicker() + }, + ), + //如果fab打开了,显示一个蒙层 + buildModal(), + ], + ), floatingActionButton: AnimatedBuilder( animation: logic.fabAnimation, builder: (context, child) { diff --git a/lib/utils/data/pref.dart b/lib/utils/data/pref.dart index dff9b42..55878fc 100644 --- a/lib/utils/data/pref.dart +++ b/lib/utils/data/pref.dart @@ -1,3 +1,4 @@ +import 'package:mood_diary/common/values/view_mode.dart'; import 'package:mood_diary/utils/utils.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -65,7 +66,6 @@ class PrefUtil { Future initPref() async { _prefs = await SharedPreferencesWithCache.create( cacheOptions: const SharedPreferencesWithCacheOptions(allowList: allowList)); - // 首次启动 var firstStart = _prefs.getBool('firstStart') ?? true; await _prefs.setBool('firstStart', firstStart); @@ -103,7 +103,7 @@ class PrefUtil { await _prefs.setBool('getWeather', _prefs.getBool('getWeather') ?? false); await _prefs.setInt('startTime', _prefs.getInt('startTime') ?? DateTime.now().millisecondsSinceEpoch); await _prefs.setString('customTitleName', _prefs.getString('customTitleName') ?? ''); - await _prefs.setString('homeViewMode', _prefs.getString('homeViewMode') ?? 'list'); + await _prefs.setInt('homeViewMode', _prefs.getInt('homeViewMode') ?? ViewModeType.list.number); } Future setValue(String key, T value) async {