diff --git a/lib/models/common/tab_type.dart b/lib/models/common/tab_type.dart index 90d19029..e530d7e5 100644 --- a/lib/models/common/tab_type.dart +++ b/lib/models/common/tab_type.dart @@ -9,6 +9,7 @@ enum TabType { live, rcmd, hot, bangumi } extension TabTypeDesc on TabType { String get description => ['直播', '推荐', '热门', '番剧'][index]; + String get id => ['live', 'rcmd', 'hot', 'bangumi'][index]; } List tabsConfig = [ diff --git a/lib/pages/home/controller.dart b/lib/pages/home/controller.dart index 614d103a..64510ee1 100644 --- a/lib/pages/home/controller.dart +++ b/lib/pages/home/controller.dart @@ -8,12 +8,13 @@ import 'package:pilipala/utils/storage.dart'; class HomeController extends GetxController with GetTickerProviderStateMixin { bool flag = false; - late List tabs; + late RxList tabs = [].obs; RxInt initialIndex = 1.obs; late TabController tabController; late List tabsCtrList; late List tabsPageList; Box userInfoCache = GStrorage.userInfo; + Box settingStorage = GStrorage.setting; RxBool userLogin = false.obs; RxString userFace = ''.obs; var userInfo; @@ -21,6 +22,8 @@ class HomeController extends GetxController with GetTickerProviderStateMixin { late final StreamController searchBarStream = StreamController.broadcast(); late bool hideSearchBar; + late List defaultTabs; + late List tabbarSort; @override void onInit() { @@ -28,34 +31,10 @@ class HomeController extends GetxController with GetTickerProviderStateMixin { userInfo = userInfoCache.get('userInfoCache'); userLogin.value = userInfo != null; userFace.value = userInfo != null ? userInfo.face : ''; - // 进行tabs配置 - tabs = tabsConfig; - tabsCtrList = tabsConfig.map((e) => e['ctr']).toList(); - tabsPageList = tabsConfig.map((e) => e['page']).toList(); - - tabController = TabController( - initialIndex: initialIndex.value, - length: tabs.length, - vsync: this, - ); + setTabConfig(); hideSearchBar = setting.get(SettingBoxKey.hideSearchBar, defaultValue: true); - - // 监听 tabController 切换 - tabController.animation!.addListener(() { - if (tabController.indexIsChanging) { - if (initialIndex.value != tabController.index) { - initialIndex.value = tabController.index; - } - } else { - final int temp = tabController.animation!.value.round(); - if (initialIndex.value != temp) { - initialIndex.value = temp; - tabController.index = initialIndex.value; - } - } - }); } void onRefresh() { @@ -77,4 +56,42 @@ class HomeController extends GetxController with GetTickerProviderStateMixin { if (val) return; userFace.value = userInfo != null ? userInfo.face : ''; } + + void setTabConfig() async { + defaultTabs = tabsConfig; + tabbarSort = settingStorage.get(SettingBoxKey.tabbarSort, + defaultValue: ['live', 'rcmd', 'hot', 'bangumi']); + + tabs.value = defaultTabs + .where((i) => tabbarSort.contains((i['type'] as TabType).id)) + .toList(); + + if (tabbarSort.contains(TabType.rcmd.id)) { + initialIndex.value = tabbarSort.indexOf(TabType.rcmd.id); + } else { + initialIndex.value = 0; + } + tabsCtrList = tabs.map((e) => e['ctr']).toList(); + tabsPageList = tabs.map((e) => e['page']).toList(); + + tabController = TabController( + initialIndex: initialIndex.value, + length: tabs.length, + vsync: this, + ); + // 监听 tabController 切换 + tabController.animation!.addListener(() { + if (tabController.indexIsChanging) { + if (initialIndex.value != tabController.index) { + initialIndex.value = tabController.index; + } + } else { + final int temp = tabController.animation!.value.round(); + if (initialIndex.value != temp) { + initialIndex.value = temp; + tabController.index = initialIndex.value; + } + } + }); + } } diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index f9823334..c31460fb 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -90,7 +90,11 @@ class _HomePageState extends State ctr: _homeController, callback: showUserBottomSheet, ), - const CustomTabs(), + if (_homeController.tabs.length > 1) ...[ + const CustomTabs(), + ] else ...[ + const SizedBox(height: 6), + ], Expanded( child: TabBarView( controller: _homeController.tabController, @@ -250,17 +254,6 @@ class CustomTabs extends StatefulWidget { class _CustomTabsState extends State { final HomeController _homeController = Get.put(HomeController()); - int currentTabIndex = 1; - - @override - void initState() { - super.initState(); - _homeController.tabController.addListener(listen); - } - - void listen() { - _homeController.initialIndex.value = _homeController.tabController.index; - } void onTap(int index) { feedBack(); @@ -271,34 +264,30 @@ class _CustomTabsState extends State { _homeController.tabController.index = index; } - @override - void dispose() { - super.dispose(); - _homeController.tabController.removeListener(listen); - } - @override Widget build(BuildContext context) { return Container( height: 44, margin: const EdgeInsets.only(top: 4), - child: ListView.separated( - padding: const EdgeInsets.symmetric(horizontal: 14.0), - scrollDirection: Axis.horizontal, - itemCount: _homeController.tabs.length, - separatorBuilder: (BuildContext context, int index) { - return const SizedBox(width: 10); - }, - itemBuilder: (BuildContext context, int index) { - String label = _homeController.tabs[index]['label']; - return Obx( - () => CustomChip( - onTap: () => onTap(index), - label: label, - selected: index == _homeController.initialIndex.value, - ), - ); - }, + child: Obx( + () => ListView.separated( + padding: const EdgeInsets.symmetric(horizontal: 14.0), + scrollDirection: Axis.horizontal, + itemCount: _homeController.tabs.length, + separatorBuilder: (BuildContext context, int index) { + return const SizedBox(width: 10); + }, + itemBuilder: (BuildContext context, int index) { + String label = _homeController.tabs[index]['label']; + return Obx( + () => CustomChip( + onTap: () => onTap(index), + label: label, + selected: index == _homeController.initialIndex.value, + ), + ); + }, + ), ), ); } diff --git a/lib/pages/setting/pages/home_tabbar_set.dart b/lib/pages/setting/pages/home_tabbar_set.dart new file mode 100644 index 00000000..445ca4f5 --- /dev/null +++ b/lib/pages/setting/pages/home_tabbar_set.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:hive/hive.dart'; +import 'package:pilipala/models/common/tab_type.dart'; +import 'package:pilipala/utils/storage.dart'; + +class TabbarSetPage extends StatefulWidget { + const TabbarSetPage({super.key}); + + @override + State createState() => _TabbarSetPageState(); +} + +class _TabbarSetPageState extends State { + Box settingStorage = GStrorage.setting; + late List defaultTabs; + late List tabbarSort; + + @override + void initState() { + super.initState(); + defaultTabs = tabsConfig; + tabbarSort = settingStorage.get(SettingBoxKey.tabbarSort, + defaultValue: ['live', 'rcmd', 'hot', 'bangumi']); + } + + void saveEdit() { + List sortedTabbar = defaultTabs + .where((i) => tabbarSort.contains((i['type'] as TabType).id)) + .map((i) => (i['type'] as TabType).id) + .toList(); + if (sortedTabbar.isEmpty) { + SmartDialog.showToast('请至少设置一项!'); + return; + } + settingStorage.put(SettingBoxKey.tabbarSort, sortedTabbar); + SmartDialog.showToast('保存成功,下次启动时生效'); + } + + void onReorder(int oldIndex, int newIndex) { + setState(() { + if (newIndex > oldIndex) { + newIndex -= 1; + } + final tabsItem = defaultTabs.removeAt(oldIndex); + defaultTabs.insert(newIndex, tabsItem); + }); + } + + @override + Widget build(BuildContext context) { + final listTiles = [ + for (int i = 0; i < defaultTabs.length; i++) ...[ + CheckboxListTile( + key: Key(defaultTabs[i]['label']), + value: tabbarSort.contains((defaultTabs[i]['type'] as TabType).id), + onChanged: (bool? newValue) { + String tabTypeId = (defaultTabs[i]['type'] as TabType).id; + if (!newValue!) { + tabbarSort.remove(tabTypeId); + } else { + tabbarSort.add(tabTypeId); + } + setState(() {}); + }, + title: Text(defaultTabs[i]['label']), + secondary: const Icon(Icons.drag_indicator_rounded), + ) + ] + ]; + + return Scaffold( + appBar: AppBar( + title: const Text('Tabbar编辑'), + actions: [ + TextButton(onPressed: () => saveEdit(), child: const Text('保存')), + const SizedBox(width: 12) + ], + ), + body: ReorderableListView( + onReorder: onReorder, + physics: const NeverScrollableScrollPhysics(), + footer: SizedBox( + height: MediaQuery.of(context).padding.bottom + 30, + ), + children: listTiles, + ), + ); + } +} diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index a4e39aa0..57ec110a 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -254,6 +254,11 @@ class _StyleSettingState extends State { onTap: () => Get.toNamed('/fontSizeSetting'), title: Text('字体大小', style: titleStyle), ), + ListTile( + dense: false, + onTap: () => Get.toNamed('/tabbarSetting'), + title: Text('首页tabbar', style: titleStyle), + ), if (Platform.isAndroid) ListTile( dense: false, diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index 996869be..64d8da31 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -36,6 +36,7 @@ import '../pages/setting/index.dart'; import '../pages/setting/pages/color_select.dart'; import '../pages/setting/pages/display_mode.dart'; import '../pages/setting/pages/font_size_select.dart'; +import '../pages/setting/pages/home_tabbar_set.dart'; import '../pages/setting/pages/play_speed_set.dart'; import '../pages/setting/play_setting.dart'; import '../pages/setting/privacy_setting.dart'; @@ -112,6 +113,8 @@ class Routes { // CustomGetPage(name: '/blackListPage', page: () => const BlackListPage()), CustomGetPage(name: '/colorSetting', page: () => const ColorSelectPage()), + // 首页tabbar + CustomGetPage(name: '/tabbarSetting', page: () => const TabbarSetPage()), CustomGetPage( name: '/fontSizeSetting', page: () => const FontSizeSelectPage()), // 屏幕帧率 diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index f59a7bc1..99037611 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -144,7 +144,8 @@ class SettingBoxKey { customRows = 'customRows', // 自定义列 enableMYBar = 'enableMYBar', hideSearchBar = 'hideSearchBar', // 收起顶栏 - hideTabBar = 'hideTabBar'; // 收起底栏 + hideTabBar = 'hideTabBar', // 收起底栏 + tabbarSort = 'tabbarSort'; // 首页tabbar } class LocalCacheKey {