mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
@@ -318,4 +318,11 @@ class DynamicsController extends GetxController
|
|||||||
.animateToTop();
|
.animateToTop();
|
||||||
scrollController.animToTop();
|
scrollController.animToTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
tabController.dispose();
|
||||||
|
scrollController.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,9 +32,8 @@ class DynamicDetailPage extends StatefulWidget {
|
|||||||
class _DynamicDetailPageState extends State<DynamicDetailPage>
|
class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||||
with TickerProviderStateMixin {
|
with TickerProviderStateMixin {
|
||||||
late DynamicDetailController _dynamicDetailController;
|
late DynamicDetailController _dynamicDetailController;
|
||||||
late AnimationController fabAnimationCtr;
|
AnimationController? _fabAnimationCtr;
|
||||||
late StreamController<bool> titleStreamC; // appBar title
|
late StreamController<bool> _titleStreamC; // appBar title
|
||||||
late ScrollController scrollController;
|
|
||||||
bool _visibleTitle = false;
|
bool _visibleTitle = false;
|
||||||
String? action;
|
String? action;
|
||||||
// 回复类型
|
// 回复类型
|
||||||
@@ -49,17 +48,17 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
super.initState();
|
super.initState();
|
||||||
// floor 1原创 2转发
|
// floor 1原创 2转发
|
||||||
init();
|
init();
|
||||||
titleStreamC = StreamController<bool>();
|
_titleStreamC = StreamController<bool>();
|
||||||
if (action == 'comment') {
|
if (action == 'comment') {
|
||||||
_visibleTitle = true;
|
_visibleTitle = true;
|
||||||
titleStreamC.add(true);
|
_titleStreamC.add(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
fabAnimationCtr = AnimationController(
|
_fabAnimationCtr = AnimationController(
|
||||||
vsync: this,
|
vsync: this,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
);
|
);
|
||||||
fabAnimationCtr.forward();
|
_fabAnimationCtr?.forward();
|
||||||
// 滚动事件监听
|
// 滚动事件监听
|
||||||
scrollListener();
|
scrollListener();
|
||||||
}
|
}
|
||||||
@@ -127,29 +126,31 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
|
|
||||||
// 滑动事件监听
|
// 滑动事件监听
|
||||||
void scrollListener() {
|
void scrollListener() {
|
||||||
scrollController = _dynamicDetailController.scrollController;
|
_dynamicDetailController.scrollController.addListener(
|
||||||
scrollController.addListener(
|
|
||||||
() {
|
() {
|
||||||
// 分页加载
|
// 分页加载
|
||||||
if (scrollController.position.pixels >=
|
if (_dynamicDetailController.scrollController.position.pixels >=
|
||||||
scrollController.position.maxScrollExtent - 300) {
|
_dynamicDetailController.scrollController.position.maxScrollExtent -
|
||||||
|
300) {
|
||||||
EasyThrottle.throttle('replylist', const Duration(seconds: 2), () {
|
EasyThrottle.throttle('replylist', const Duration(seconds: 2), () {
|
||||||
_dynamicDetailController.onLoadMore();
|
_dynamicDetailController.onLoadMore();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标题
|
// 标题
|
||||||
if (scrollController.offset > 55 && !_visibleTitle) {
|
if (_dynamicDetailController.scrollController.offset > 55 &&
|
||||||
|
!_visibleTitle) {
|
||||||
_visibleTitle = true;
|
_visibleTitle = true;
|
||||||
titleStreamC.add(true);
|
_titleStreamC.add(true);
|
||||||
} else if (scrollController.offset <= 55 && _visibleTitle) {
|
} else if (_dynamicDetailController.scrollController.offset <= 55 &&
|
||||||
|
_visibleTitle) {
|
||||||
_visibleTitle = false;
|
_visibleTitle = false;
|
||||||
titleStreamC.add(false);
|
_titleStreamC.add(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fab按钮
|
// fab按钮
|
||||||
final ScrollDirection direction =
|
final ScrollDirection direction = _dynamicDetailController
|
||||||
scrollController.position.userScrollDirection;
|
.scrollController.position.userScrollDirection;
|
||||||
if (direction == ScrollDirection.forward) {
|
if (direction == ScrollDirection.forward) {
|
||||||
_showFab();
|
_showFab();
|
||||||
} else if (direction == ScrollDirection.reverse) {
|
} else if (direction == ScrollDirection.reverse) {
|
||||||
@@ -162,22 +163,23 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
void _showFab() {
|
void _showFab() {
|
||||||
if (!_isFabVisible) {
|
if (!_isFabVisible) {
|
||||||
_isFabVisible = true;
|
_isFabVisible = true;
|
||||||
fabAnimationCtr.forward();
|
_fabAnimationCtr?.forward();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _hideFab() {
|
void _hideFab() {
|
||||||
if (_isFabVisible) {
|
if (_isFabVisible) {
|
||||||
_isFabVisible = false;
|
_isFabVisible = false;
|
||||||
fabAnimationCtr.reverse();
|
_fabAnimationCtr?.reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
titleStreamC.close();
|
_titleStreamC.close();
|
||||||
fabAnimationCtr.dispose();
|
_fabAnimationCtr?.dispose();
|
||||||
scrollController.removeListener(() {});
|
_fabAnimationCtr = null;
|
||||||
|
_dynamicDetailController.scrollController.removeListener(() {});
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +188,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: StreamBuilder(
|
title: StreamBuilder(
|
||||||
stream: titleStreamC.stream,
|
stream: _titleStreamC.stream,
|
||||||
initialData: false,
|
initialData: false,
|
||||||
builder: (context, AsyncSnapshot snapshot) {
|
builder: (context, AsyncSnapshot snapshot) {
|
||||||
return AnimatedOpacity(
|
return AnimatedOpacity(
|
||||||
@@ -212,7 +214,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
double padding = max(context.width / 2 - Grid.maxRowWidth, 0);
|
double padding = max(context.width / 2 - Grid.maxRowWidth, 0);
|
||||||
if (orientation == Orientation.portrait) {
|
if (orientation == Orientation.portrait) {
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
controller: scrollController,
|
controller: _dynamicDetailController.scrollController,
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
@@ -252,7 +254,8 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
controller: scrollController,
|
controller:
|
||||||
|
_dynamicDetailController.scrollController,
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
@@ -276,30 +279,31 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Positioned(
|
if (_fabAnimationCtr != null)
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 14,
|
Positioned(
|
||||||
right: 14,
|
bottom: MediaQuery.of(context).padding.bottom + 14,
|
||||||
child: SlideTransition(
|
right: 14,
|
||||||
position: Tween<Offset>(
|
child: SlideTransition(
|
||||||
begin: const Offset(0, 2),
|
position: Tween<Offset>(
|
||||||
end: const Offset(0, 0),
|
begin: const Offset(0, 2),
|
||||||
).animate(CurvedAnimation(
|
end: const Offset(0, 0),
|
||||||
parent: fabAnimationCtr,
|
).animate(CurvedAnimation(
|
||||||
curve: Curves.easeInOut,
|
parent: _fabAnimationCtr!,
|
||||||
)),
|
curve: Curves.easeInOut,
|
||||||
child: FloatingActionButton(
|
)),
|
||||||
heroTag: null,
|
child: FloatingActionButton(
|
||||||
onPressed: () {
|
heroTag: null,
|
||||||
feedBack();
|
onPressed: () {
|
||||||
dynamic oid = _dynamicDetailController.oid ??
|
feedBack();
|
||||||
IdUtils.bv2av(Get.parameters['bvid']!);
|
dynamic oid = _dynamicDetailController.oid ??
|
||||||
_dynamicDetailController.onReply(context, oid: oid);
|
IdUtils.bv2av(Get.parameters['bvid']!);
|
||||||
},
|
_dynamicDetailController.onReply(context, oid: oid);
|
||||||
tooltip: '评论动态',
|
},
|
||||||
child: const Icon(Icons.reply),
|
tooltip: '评论动态',
|
||||||
|
child: const Icon(Icons.reply),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -118,9 +118,7 @@ class _DynamicsPageState extends State<DynamicsPage>
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_dynamicsController.tabController.removeListener(() {});
|
_dynamicsController.tabController.removeListener(() {});
|
||||||
_dynamicsController.tabController.dispose();
|
|
||||||
_dynamicsController.scrollController.removeListener(() {});
|
_dynamicsController.scrollController.removeListener(() {});
|
||||||
_dynamicsController.scrollController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,14 +114,18 @@ class _EmotePanelState extends State<EmotePanel>
|
|||||||
SizedBox(height: MediaQuery.of(context).padding.bottom),
|
SizedBox(height: MediaQuery.of(context).padding.bottom),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: errorWidget(
|
: _errorWidget,
|
||||||
callback: _emotePanelController.onReload,
|
Error() => _errorWidget,
|
||||||
),
|
|
||||||
Error() => errorWidget(
|
|
||||||
errMsg: loadingState.errMsg,
|
|
||||||
callback: _emotePanelController.onReload,
|
|
||||||
),
|
|
||||||
LoadingState() => throw UnimplementedError(),
|
LoadingState() => throw UnimplementedError(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget get _errorWidget => Center(
|
||||||
|
child: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
_emotePanelController.onReload();
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.refresh),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,4 +205,10 @@ class HistoryController extends GetxController {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
scrollController.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,17 +21,16 @@ class HistoryPage extends StatefulWidget {
|
|||||||
class _HistoryPageState extends State<HistoryPage> {
|
class _HistoryPageState extends State<HistoryPage> {
|
||||||
final HistoryController _historyController = Get.put(HistoryController());
|
final HistoryController _historyController = Get.put(HistoryController());
|
||||||
Future? _futureBuilderFuture;
|
Future? _futureBuilderFuture;
|
||||||
late ScrollController scrollController;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_futureBuilderFuture = _historyController.queryHistoryList();
|
_futureBuilderFuture = _historyController.queryHistoryList();
|
||||||
scrollController = _historyController.scrollController;
|
_historyController.scrollController.addListener(
|
||||||
scrollController.addListener(
|
|
||||||
() {
|
() {
|
||||||
if (scrollController.position.pixels >=
|
if (_historyController.scrollController.position.pixels >=
|
||||||
scrollController.position.maxScrollExtent - 300) {
|
_historyController.scrollController.position.maxScrollExtent -
|
||||||
|
300) {
|
||||||
if (!_historyController.isLoadingMore.value) {
|
if (!_historyController.isLoadingMore.value) {
|
||||||
EasyThrottle.throttle('history', const Duration(seconds: 1), () {
|
EasyThrottle.throttle('history', const Duration(seconds: 1), () {
|
||||||
_historyController.onLoad();
|
_historyController.onLoad();
|
||||||
@@ -61,8 +60,7 @@ class _HistoryPageState extends State<HistoryPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
scrollController.removeListener(() {});
|
_historyController.scrollController.removeListener(() {});
|
||||||
scrollController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
tabController.animation!.removeListener(() {});
|
tabController.animation!.removeListener(() {});
|
||||||
|
tabController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,4 +64,10 @@ class MemberArchiveController extends GetxController {
|
|||||||
Future onLoad() async {
|
Future onLoad() async {
|
||||||
getMemberArchive('onLoad');
|
getMemberArchive('onLoad');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
scrollController.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ class _MemberArchivePageState extends State<MemberArchivePage> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_memberArchivesController.scrollController.removeListener(() {});
|
_memberArchivesController.scrollController.removeListener(() {});
|
||||||
_memberArchivesController.scrollController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,4 +90,11 @@ class MemberSearchController extends GetxController {
|
|||||||
onLoad() {
|
onLoad() {
|
||||||
searchArchives(type: 'onLoad');
|
searchArchives(type: 'onLoad');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
searchFocusNode.dispose();
|
||||||
|
scrollController.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,16 +20,14 @@ class _MemberSearchPageState extends State<MemberSearchPage>
|
|||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
final MemberSearchController _memberSearchCtr =
|
final MemberSearchController _memberSearchCtr =
|
||||||
Get.put(MemberSearchController());
|
Get.put(MemberSearchController());
|
||||||
late ScrollController scrollController;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
scrollController = _memberSearchCtr.scrollController;
|
_memberSearchCtr.scrollController.addListener(
|
||||||
scrollController.addListener(
|
|
||||||
() {
|
() {
|
||||||
if (scrollController.position.pixels >=
|
if (_memberSearchCtr.scrollController.position.pixels >=
|
||||||
scrollController.position.maxScrollExtent - 300) {
|
_memberSearchCtr.scrollController.position.maxScrollExtent - 300) {
|
||||||
EasyThrottle.throttle('history', const Duration(seconds: 1), () {
|
EasyThrottle.throttle('history', const Duration(seconds: 1), () {
|
||||||
_memberSearchCtr.onLoad();
|
_memberSearchCtr.onLoad();
|
||||||
});
|
});
|
||||||
@@ -42,9 +40,7 @@ class _MemberSearchPageState extends State<MemberSearchPage>
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
// _tabController.dispose();
|
// _tabController.dispose();
|
||||||
_memberSearchCtr.searchFocusNode.dispose();
|
_memberSearchCtr.scrollController.removeListener(() {});
|
||||||
scrollController.removeListener(() {});
|
|
||||||
scrollController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +90,7 @@ class _MemberSearchPageState extends State<MemberSearchPage>
|
|||||||
}
|
}
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
controller: scrollController,
|
controller: _memberSearchCtr.scrollController,
|
||||||
slivers: <Widget>[
|
slivers: <Widget>[
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: _memberSearchCtr.searchArchives(),
|
future: _memberSearchCtr.searchArchives(),
|
||||||
|
|||||||
@@ -44,4 +44,10 @@ class MemberSeasonsController extends GetxController {
|
|||||||
Future onLoad() async {
|
Future onLoad() async {
|
||||||
getSeasonDetail('onLoad');
|
getSeasonDetail('onLoad');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
scrollController.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ class _MemberSeasonsPageState extends State<MemberSeasonsPage> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_memberSeasonsController.scrollController.removeListener(() {});
|
_memberSeasonsController.scrollController.removeListener(() {});
|
||||||
_memberSeasonsController.scrollController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,4 +64,10 @@ class RankController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
tabController.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,12 +23,6 @@ class _RankPageState extends State<RankPage>
|
|||||||
TabController(vsync: this, length: _rankController.tabs.length);
|
TabController(vsync: this, length: _rankController.tabs.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_rankController.tabController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
|
|||||||
@@ -130,4 +130,10 @@ class SSearchController extends GetxController {
|
|||||||
historyList.refresh();
|
historyList.refresh();
|
||||||
historyWord.put('cacheList', []);
|
historyWord.put('cacheList', []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
searchFocusNode.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ class _SearchPageState extends State<SearchPage> with RouteAware {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_searchController.searchFocusNode.dispose();
|
|
||||||
SearchPage.routeObserver.unsubscribe(this);
|
SearchPage.routeObserver.unsubscribe(this);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,4 +83,10 @@ class SubController extends GetxController {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
scrollController.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ class _SubPageState extends State<SubPage> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_subController.scrollController.removeListener(() {});
|
_subController.scrollController.removeListener(() {});
|
||||||
_subController.scrollController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class _PagesPanelState extends State<PagesPanel> {
|
|||||||
// final String heroTag = Get.arguments['heroTag'];
|
// final String heroTag = Get.arguments['heroTag'];
|
||||||
late final String heroTag;
|
late final String heroTag;
|
||||||
late VideoDetailController _videoDetailController;
|
late VideoDetailController _videoDetailController;
|
||||||
final ScrollController _scrollController2 = ScrollController();
|
final ScrollController _scrollController = ScrollController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -50,9 +50,9 @@ class _PagesPanelState extends State<PagesPanel> {
|
|||||||
const double itemWidth = 150; // 每个列表项的宽度
|
const double itemWidth = 150; // 每个列表项的宽度
|
||||||
final double targetOffset = min(
|
final double targetOffset = min(
|
||||||
(currentIndex * itemWidth) - (itemWidth / 2),
|
(currentIndex * itemWidth) - (itemWidth / 2),
|
||||||
_scrollController2.position.maxScrollExtent);
|
_scrollController.position.maxScrollExtent);
|
||||||
// 滑动至目标位置
|
// 滑动至目标位置
|
||||||
_scrollController2.animateTo(
|
_scrollController.animateTo(
|
||||||
targetOffset,
|
targetOffset,
|
||||||
duration: const Duration(milliseconds: 300), // 滑动动画持续时间
|
duration: const Duration(milliseconds: 300), // 滑动动画持续时间
|
||||||
curve: Curves.easeInOut, // 滑动动画曲线
|
curve: Curves.easeInOut, // 滑动动画曲线
|
||||||
@@ -62,7 +62,7 @@ class _PagesPanelState extends State<PagesPanel> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_scrollController2.dispose();
|
_scrollController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ class _PagesPanelState extends State<PagesPanel> {
|
|||||||
height: 35,
|
height: 35,
|
||||||
margin: const EdgeInsets.only(bottom: 8),
|
margin: const EdgeInsets.only(bottom: 8),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
controller: _scrollController2,
|
controller: _scrollController,
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
itemCount: widget.pages.length,
|
itemCount: widget.pages.length,
|
||||||
itemExtent: 150,
|
itemExtent: 150,
|
||||||
|
|||||||
@@ -106,4 +106,10 @@ class WhisperDetailController extends GetxController {
|
|||||||
SmartDialog.showToast(result['msg']);
|
SmartDialog.showToast(result['msg']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
replyContentController.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ class _WhisperDetailPageState extends State<WhisperDetailPage> {
|
|||||||
_readOnlyStream.close();
|
_readOnlyStream.close();
|
||||||
_enableSend.close();
|
_enableSend.close();
|
||||||
_focusNode.dispose();
|
_focusNode.dispose();
|
||||||
_whisperDetailController.replyContentController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user