diff --git a/lib/common/widgets/episode_panel.dart b/lib/common/widgets/episode_panel.dart index f47b2def3..d0fd49980 100644 --- a/lib/common/widgets/episode_panel.dart +++ b/lib/common/widgets/episode_panel.dart @@ -6,7 +6,7 @@ import 'package:PiliPlus/common/widgets/icon_button.dart'; import 'package:PiliPlus/common/widgets/image_save.dart'; import 'package:PiliPlus/common/widgets/keep_alive_wrapper.dart'; import 'package:PiliPlus/common/widgets/network_img_layer.dart'; -import 'package:PiliPlus/common/widgets/spring_physics.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/stat/stat.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/video.dart'; diff --git a/lib/common/widgets/spring_physics.dart b/lib/common/widgets/scroll_physics.dart similarity index 63% rename from lib/common/widgets/spring_physics.dart rename to lib/common/widgets/scroll_physics.dart index 16b4b2e3f..0cfefa78a 100644 --- a/lib/common/widgets/spring_physics.dart +++ b/lib/common/widgets/scroll_physics.dart @@ -52,3 +52,35 @@ class CustomTabBarViewClampingScrollPhysics extends ClampingScrollPhysics { damping: GStorage.springDescription[2], ); } + +class PositionRetainedScrollPhysics extends AlwaysScrollableScrollPhysics { + const PositionRetainedScrollPhysics({super.parent}); + + @override + PositionRetainedScrollPhysics applyTo(ScrollPhysics? ancestor) { + return PositionRetainedScrollPhysics(parent: buildParent(ancestor)); + } + + @override + double adjustPositionForNewDimensions({ + required ScrollMetrics oldPosition, + required ScrollMetrics newPosition, + required bool isScrolling, + required double velocity, + }) { + final position = super.adjustPositionForNewDimensions( + oldPosition: oldPosition, + newPosition: newPosition, + isScrolling: isScrolling, + velocity: velocity, + ); + + final diff = newPosition.maxScrollExtent - oldPosition.maxScrollExtent; + + if (oldPosition.pixels >= oldPosition.minScrollExtent && diff > 0) { + return position + diff; + } else { + return position; + } + } +} diff --git a/lib/pages/bangumi/view.dart b/lib/pages/bangumi/view.dart index 5013a1bc3..ca748b59b 100644 --- a/lib/pages/bangumi/view.dart +++ b/lib/pages/bangumi/view.dart @@ -16,7 +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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; class BangumiPage extends StatefulWidget { const BangumiPage({ diff --git a/lib/pages/danmaku_block/index.dart b/lib/pages/danmaku_block/index.dart index eead3b87c..39b0b8fe2 100644 --- a/lib/pages/danmaku_block/index.dart +++ b/lib/pages/danmaku_block/index.dart @@ -7,7 +7,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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; class DanmakuBlockPage extends StatefulWidget { const DanmakuBlockPage({super.key}); diff --git a/lib/pages/dynamics/view.dart b/lib/pages/dynamics/view.dart index b9bf5f2c6..97d8e3da1 100644 --- a/lib/pages/dynamics/view.dart +++ b/lib/pages/dynamics/view.dart @@ -11,7 +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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; enum ReplyOption { allow, close, choose } diff --git a/lib/pages/emote/view.dart b/lib/pages/emote/view.dart index 06a477389..4235b6eff 100644 --- a/lib/pages/emote/view.dart +++ b/lib/pages/emote/view.dart @@ -5,7 +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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; class EmotePanel extends StatefulWidget { final Function onChoose; diff --git a/lib/pages/follow/view.dart b/lib/pages/follow/view.dart index 9312341f0..dcdbad6e0 100644 --- a/lib/pages/follow/view.dart +++ b/lib/pages/follow/view.dart @@ -5,7 +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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; class FollowPage extends StatefulWidget { const FollowPage({super.key}); diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index f64b82ae4..b698bdd5c 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -8,7 +8,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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:stream_transform/stream_transform.dart'; class HomePage extends StatefulWidget { diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index 9fc1c371c..7c83b86d3 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -1,7 +1,7 @@ import 'dart:ui'; import 'package:PiliPlus/common/constants.dart'; -import 'package:PiliPlus/common/widgets/spring_physics.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; diff --git a/lib/pages/member/new/content/member_contribute/content/video/member_video.dart b/lib/pages/member/new/content/member_contribute/content/video/member_video.dart index 0e4db0aa6..e279436f4 100644 --- a/lib/pages/member/new/content/member_contribute/content/video/member_video.dart +++ b/lib/pages/member/new/content/member_contribute/content/video/member_video.dart @@ -2,8 +2,10 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart'; import 'package:PiliPlus/common/widgets/loading_widget.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/video_card_h_member_video.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/space_archive/item.dart'; import 'package:PiliPlus/pages/member/new/content/member_contribute/content/video/member_video_ctr.dart'; import 'package:PiliPlus/pages/member/new/content/member_contribute/member_contribute.dart' show ContributeType; @@ -70,6 +72,7 @@ class _MemberVideoState extends State await _controller.onRefresh(); }, child: CustomScrollView( + physics: const PositionRetainedScrollPhysics(), slivers: [ SliverPersistentHeader( pinned: false, @@ -183,8 +186,10 @@ class _MemberVideoState extends State index == loadingState.response.length - 1) { _controller.onLoadMore(); } + final Item item = loadingState.response[index]; return VideoCardHMemberVideo( - videoItem: loadingState.response[index], + key: ValueKey('${item.param}'), + videoItem: item, fromViewAid: _controller.fromViewAid, ); }, diff --git a/lib/pages/member/new/member_page.dart b/lib/pages/member/new/member_page.dart index f256728f6..11fa83bcc 100644 --- a/lib/pages/member/new/member_page.dart +++ b/lib/pages/member/new/member_page.dart @@ -15,7 +15,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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; class MemberPageNew extends StatefulWidget { const MemberPageNew({super.key}); diff --git a/lib/pages/member_search/view.dart b/lib/pages/member_search/view.dart index ccf3f3f0c..dd25e7c6d 100644 --- a/lib/pages/member_search/view.dart +++ b/lib/pages/member_search/view.dart @@ -3,7 +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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; class MemberSearchPage extends StatefulWidget { const MemberSearchPage({super.key}); diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index fdfee93cc..e0bb8a7c5 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -5,7 +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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; class SearchResultPage extends StatefulWidget { const SearchResultPage({super.key}); diff --git a/lib/pages/video/detail/member/horizontal_member_page.dart b/lib/pages/video/detail/member/horizontal_member_page.dart index 74cfdd790..f11c9bb6c 100644 --- a/lib/pages/video/detail/member/horizontal_member_page.dart +++ b/lib/pages/video/detail/member/horizontal_member_page.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/interactiveviewer_gallery/interactivevie show SourceModel; import 'package:PiliPlus/common/widgets/loading_widget.dart'; import 'package:PiliPlus/common/widgets/network_img_layer.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/video_card_h_member_video.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/member/info.dart'; @@ -179,7 +180,7 @@ class _HorizontalMemberPageState extends State { color: Colors.transparent, child: CustomScrollView( controller: _controller.scrollController, - physics: const AlwaysScrollableScrollPhysics(), + physics: const PositionRetainedScrollPhysics(), slivers: [ _buildSliverHeader, SliverPadding( @@ -198,11 +199,12 @@ class _HorizontalMemberPageState extends State { _controller.hasNext) { _controller.onLoadMore(); } + final Item videoItem = loadingState.response[index]; return VideoCardHMemberVideo( - videoItem: loadingState.response[index], + key: ValueKey('${videoItem.param}'), + videoItem: videoItem, bvid: _bvid, onTap: () { - final Item videoItem = loadingState.response[index]; final status = widget.videoIntroController.changeSeasonOrbangu( null, diff --git a/lib/pages/video/detail/view_v.dart b/lib/pages/video/detail/view_v.dart index 6aa6fcc37..bc7363a98 100644 --- a/lib/pages/video/detail/view_v.dart +++ b/lib/pages/video/detail/view_v.dart @@ -51,7 +51,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'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; class VideoDetailPageV extends StatefulWidget { const VideoDetailPageV({super.key}); diff --git a/lib/pages/video/detail/widgets/media_list_panel.dart b/lib/pages/video/detail/widgets/media_list_panel.dart index 5979e6cbf..62ebb58c7 100644 --- a/lib/pages/video/detail/widgets/media_list_panel.dart +++ b/lib/pages/video/detail/widgets/media_list_panel.dart @@ -2,6 +2,7 @@ import 'package:PiliPlus/common/widgets/dialog.dart'; import 'package:PiliPlus/common/widgets/icon_button.dart'; import 'package:PiliPlus/common/widgets/image_save.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/stat/stat.dart'; import 'package:PiliPlus/pages/common/common_collapse_slide_page.dart'; import 'package:flutter/material.dart'; @@ -126,7 +127,7 @@ class _MediaListPanelState widget.onDelete != null && widget.mediaList.length > 1; return ScrollablePositionedList.separated( itemScrollController: _scrollController, - physics: const AlwaysScrollableScrollPhysics(), + physics: const PositionRetainedScrollPhysics(), itemCount: widget.mediaList.length, padding: EdgeInsets.only( top: 7, @@ -140,6 +141,7 @@ class _MediaListPanelState widget.loadMoreMedia(); } return SizedBox( + key: ValueKey('${item.aid}'), height: 98, child: InkWell( onTap: () async {