diff --git a/lib/common/widgets/list_sheet.dart b/lib/common/widgets/list_sheet.dart index 7ab6d7c5..5376e3cd 100644 --- a/lib/common/widgets/list_sheet.dart +++ b/lib/common/widgets/list_sheet.dart @@ -14,6 +14,7 @@ import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import '../../utils/storage.dart'; import '../../utils/utils.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class ListSheetContent extends StatefulWidget { const ListSheetContent({ @@ -423,6 +424,7 @@ class _ListSheetContentState extends State ? Material( color: Colors.transparent, child: TabBarView( + physics: customTabBarViewScrollPhysics, controller: _ctr, children: List.generate( widget.season.sections.length, diff --git a/lib/common/widgets/spring_physics.dart b/lib/common/widgets/spring_physics.dart new file mode 100644 index 00000000..d4bbd19b --- /dev/null +++ b/lib/common/widgets/spring_physics.dart @@ -0,0 +1,20 @@ +import 'package:flutter/cupertino.dart'; +import 'package:PiliPlus/utils/storage.dart'; + +class CustomTabBarViewScrollPhysics extends ScrollPhysics { + CustomTabBarViewScrollPhysics({super.parent}); + + @override + CustomTabBarViewScrollPhysics applyTo(ScrollPhysics? ancestor) { + return CustomTabBarViewScrollPhysics(parent: buildParent(ancestor)!); + } + + @override + SpringDescription spring = SpringDescription( + mass: GStorage.springDescription[0], + stiffness: GStorage.springDescription[1], + damping: GStorage.springDescription[2] + ); +} + +final customTabBarViewScrollPhysics = CustomTabBarViewScrollPhysics(); \ No newline at end of file diff --git a/lib/pages/bangumi/view.dart b/lib/pages/bangumi/view.dart index 78077f35..300e35ee 100644 --- a/lib/pages/bangumi/view.dart +++ b/lib/pages/bangumi/view.dart @@ -16,6 +16,7 @@ import 'package:PiliPlus/pages/main/index.dart'; import '../../utils/grid.dart'; import 'controller.dart'; import 'widgets/bangumi_card_v.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class BangumiPage extends StatefulWidget { const BangumiPage({ @@ -162,6 +163,7 @@ class _BangumiPageState extends State .toList()), Expanded( child: TabBarView( + physics: customTabBarViewScrollPhysics, children: types .map((type) => PgcIndexPage(indexType: type)) diff --git a/lib/pages/danmaku_block/index.dart b/lib/pages/danmaku_block/index.dart index b75dd2a2..d3f6c68a 100644 --- a/lib/pages/danmaku_block/index.dart +++ b/lib/pages/danmaku_block/index.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/utils/storage.dart'; import '../../http/danmaku_block.dart'; import '../../models/user/danmaku_block.dart'; import '../../plugin/pl_player/controller.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class DanmakuBlockPage extends StatefulWidget { const DanmakuBlockPage({super.key}); @@ -142,6 +143,7 @@ class _DanmakuBlockPageState extends State { ]), ), body: TabBarView( + physics: customTabBarViewScrollPhysics, controller: _danmakuBlockController.tabController, children: [ for (var i = 0; i < ruleLabels.length; i++) diff --git a/lib/pages/dynamics/view.dart b/lib/pages/dynamics/view.dart index 32ef5482..d682a2f6 100644 --- a/lib/pages/dynamics/view.dart +++ b/lib/pages/dynamics/view.dart @@ -11,6 +11,7 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart import 'controller.dart'; import 'widgets/up_panel.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; enum ReplyOption { allow, close, choose } @@ -183,7 +184,7 @@ class _DynamicsPageState extends State if (upPanelPosition == UpPanelPosition.leftFixed) upPanelPart(), Expanded( child: TabBarView( - physics: const AlwaysScrollableScrollPhysics(), + physics: customTabBarViewScrollPhysics, controller: _dynamicsController.tabController, children: _dynamicsController.tabsPageList, )), diff --git a/lib/pages/emote/view.dart b/lib/pages/emote/view.dart index 76b90509..a8e08f88 100644 --- a/lib/pages/emote/view.dart +++ b/lib/pages/emote/view.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../common/widgets/network_img_layer.dart'; import 'controller.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class EmotePanel extends StatefulWidget { final Function onChoose; @@ -36,6 +37,7 @@ class _EmotePanelState extends State children: [ Expanded( child: TabBarView( + physics: customTabBarViewScrollPhysics, controller: _emotePanelController.tabController, children: (loadingState.response as List).map( (e) { diff --git a/lib/pages/follow/view.dart b/lib/pages/follow/view.dart index 39df6511..1cdec44c 100644 --- a/lib/pages/follow/view.dart +++ b/lib/pages/follow/view.dart @@ -5,6 +5,7 @@ import 'package:get/get.dart'; import 'controller.dart'; import 'widgets/follow_list.dart'; import 'widgets/owner_follow_list.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class FollowPage extends StatefulWidget { const FollowPage({super.key}); @@ -83,6 +84,7 @@ class _FollowPageState extends State { ]), Expanded( child: TabBarView( + physics: customTabBarViewScrollPhysics, controller: _followController.tabController, children: [ for (var i = 0; diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index 34812b30..7c81ae3f 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -10,6 +10,7 @@ import 'package:PiliPlus/common/widgets/network_img_layer.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import './controller.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @@ -73,6 +74,7 @@ class _HomePageState extends State const SizedBox(height: 6), Expanded( child: TabBarView( + physics: customTabBarViewScrollPhysics, controller: _homeController.tabController, children: _homeController.tabsPageList, ), diff --git a/lib/pages/member/new/member_page.dart b/lib/pages/member/new/member_page.dart index 1f134161..24a64041 100644 --- a/lib/pages/member/new/member_page.dart +++ b/lib/pages/member/new/member_page.dart @@ -16,6 +16,7 @@ import 'package:PiliPlus/utils/utils.dart'; import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class MemberPageNew extends StatefulWidget { const MemberPageNew({super.key}); @@ -151,6 +152,7 @@ class _MemberPageNewState extends State top: false, bottom: false, child: TabBarView( + physics: customTabBarViewScrollPhysics, controller: _userController.tabController, children: _userController.tab2!.map((item) { return switch (item.param!) { diff --git a/lib/pages/member_search/view.dart b/lib/pages/member_search/view.dart index 722b903c..0c8bc25a 100644 --- a/lib/pages/member_search/view.dart +++ b/lib/pages/member_search/view.dart @@ -3,6 +3,7 @@ import 'package:PiliPlus/pages/member_search/search_dynamic.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'controller.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class MemberSearchPage extends StatefulWidget { const MemberSearchPage({super.key}); @@ -69,6 +70,7 @@ class _MemberSearchPageState extends State { ), Expanded( child: TabBarView( + physics: customTabBarViewScrollPhysics, controller: _memberSearchCtr.tabController, children: [ SearchArchive(ctr: _memberSearchCtr), diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index ed3f20b3..1596e2b9 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -5,6 +5,7 @@ import 'package:get/get.dart'; import 'package:PiliPlus/models/common/search_type.dart'; import 'package:PiliPlus/pages/search_panel/index.dart'; import 'controller.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class SearchResultPage extends StatefulWidget { const SearchResultPage({super.key}); @@ -119,6 +120,7 @@ class _SearchResultPageState extends State ), Expanded( child: TabBarView( + physics: customTabBarViewScrollPhysics, controller: _tabController, children: SearchType.values .map( diff --git a/lib/pages/setting/widgets/model.dart b/lib/pages/setting/widgets/model.dart index 7280db4b..1f35c227 100644 --- a/lib/pages/setting/widgets/model.dart +++ b/lib/pages/setting/widgets/model.dart @@ -536,6 +536,75 @@ List get styleSettings => [ getSubtitle: () => '当前启动页:${defaultNavigationBars.firstWhere((e) => e['id'] == GStorage.defaultHomePage)['label']}', ), + SettingsModel( + settingsType: SettingsType.normal, + title: '滑动动画弹簧参数', + leading: const Icon(Icons.chrome_reader_mode_outlined), + onTap: (setState) { + final numberRegExp = RegExp(r'[\d\.]+'); + List springDescription = GStorage.springDescription.map((i) => i.toString()).toList(); + showDialog( + context: Get.context!, + builder: (context) { + return AlertDialog( + title: const Text('弹簧参数'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + autofocus: true, + initialValue: springDescription[0], + keyboardType: TextInputType.numberWithOptions(), + onChanged: (value) { springDescription[0] = value; }, + inputFormatters: [FilteringTextInputFormatter.allow(numberRegExp)], + decoration: InputDecoration(labelText: 'mass'), + ), + TextFormField( + autofocus: true, + initialValue: springDescription[1], + keyboardType: TextInputType.numberWithOptions(), + onChanged: (value) { springDescription[1] = value; }, + inputFormatters: [FilteringTextInputFormatter.allow(numberRegExp)], + decoration: InputDecoration(labelText: 'stiffness'), + ), + TextFormField( + autofocus: true, + initialValue: springDescription[2], + keyboardType: TextInputType.numberWithOptions(), + onChanged: (value) { springDescription[2] = value; }, + inputFormatters: [FilteringTextInputFormatter.allow(numberRegExp)], + decoration: InputDecoration(labelText: 'damping'), + ) + ] + ), + actions: [ + TextButton( + onPressed: Get.back, + child: Text( + '取消', + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + ), + ), + ), + TextButton( + onPressed: () async { + Get.back(); + await GStorage.setting.put( + SettingBoxKey.springDescription, + List.generate(3, (i) => double.tryParse(springDescription[i]) ?? GStorage.springDescription[i]), + ); + SmartDialog.showToast('设置成功,重启生效'); + setState(); + }, + child: const Text('确定'), + ) + ], + ); + }, + ); + }, + ), SettingsModel( settingsType: SettingsType.normal, onTap: (setState) async { diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index bda919e6..2d36719c 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -50,6 +50,7 @@ import 'package:screen_brightness/screen_brightness.dart'; import '../../../services/shutdown_timer_service.dart'; import 'widgets/header_control.dart'; +import 'package:PiliPlus/common/widgets/spring_physics.dart'; class VideoDetailPage extends StatefulWidget { const VideoDetailPage({super.key}); @@ -621,7 +622,7 @@ class _VideoDetailPageState extends State ), Expanded( child: TabBarView( - physics: const ClampingScrollPhysics(), + physics: customTabBarViewScrollPhysics, controller: videoDetailController.tabCtr, children: [ videoIntro(), @@ -672,7 +673,7 @@ class _VideoDetailPageState extends State buildTabbar(showReply: videoDetailController.showReply), Expanded( child: TabBarView( - physics: const ClampingScrollPhysics(), + physics: customTabBarViewScrollPhysics, controller: videoDetailController.tabCtr, children: [ videoIntro(), @@ -772,6 +773,7 @@ class _VideoDetailPageState extends State ), Expanded( child: TabBarView( + physics: customTabBarViewScrollPhysics, controller: videoDetailController.tabCtr, children: [ if (videoDetailController.showReply) @@ -881,7 +883,7 @@ class _VideoDetailPageState extends State ), Expanded( child: TabBarView( - physics: const ClampingScrollPhysics(), + physics: customTabBarViewScrollPhysics, controller: videoDetailController.tabCtr, children: [ if (videoDetailController.videoType == diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index fde6a6de..5bea1008 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -415,6 +415,12 @@ class GStorage { }; } + static final _defaultSpring = const ClampingScrollPhysics().spring; + + static final List springDescription = setting + .get(SettingBoxKey.springDescription, + defaultValue: [_defaultSpring.mass, _defaultSpring.stiffness, _defaultSpring.damping]); + // static Brightness get brightness { // return switch (_themeMode) { // 0 => Brightness.light, @@ -625,6 +631,7 @@ class SettingBoxKey { antiGoodsDyn = 'antiGoodsDyn', antiGoodsReply = 'antiGoodsReply', expandDynLivePanel = 'expandDynLivePanel', + springDescription = 'springDescription', // Sponsor Block enableSponsorBlock = 'enableSponsorBlock',