diff --git a/lib/common/skeleton/media_bangumi.dart b/lib/common/skeleton/media_bangumi.dart index cf589254..98282cf0 100644 --- a/lib/common/skeleton/media_bangumi.dart +++ b/lib/common/skeleton/media_bangumi.dart @@ -3,14 +3,9 @@ import 'package:pilipala/common/constants.dart'; import 'skeleton.dart'; -class MediaBangumiSkeleton extends StatefulWidget { +class MediaBangumiSkeleton extends StatelessWidget { const MediaBangumiSkeleton({super.key}); - @override - State createState() => _MediaBangumiSkeletonState(); -} - -class _MediaBangumiSkeletonState extends State { @override Widget build(BuildContext context) { Color bgColor = Theme.of(context).colorScheme.onInverseSurface; @@ -35,25 +30,25 @@ class _MediaBangumiSkeletonState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, width: 200, height: 20, margin: const EdgeInsets.only(bottom: 15), ), Container( - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, width: 150, height: 13, margin: const EdgeInsets.only(bottom: 5), ), Container( - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, width: 150, height: 13, margin: const EdgeInsets.only(bottom: 5), ), Container( - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, width: 150, height: 13, ), @@ -64,7 +59,7 @@ class _MediaBangumiSkeletonState extends State { decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(20)), - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, ), ), ], diff --git a/lib/common/skeleton/user_list.dart b/lib/common/skeleton/user_list.dart new file mode 100644 index 00000000..cd9d4eb3 --- /dev/null +++ b/lib/common/skeleton/user_list.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import '../constants.dart'; + +class UserListSkeleton extends StatelessWidget { + const UserListSkeleton({super.key}); + + @override + Widget build(BuildContext context) { + Color bgColor = Theme.of(context).colorScheme.onInverseSurface; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, vertical: 7), + child: Row( + children: [ + ClipOval( + child: Container(width: 42, height: 42, color: bgColor), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container(color: bgColor, width: 60, height: 13), + const SizedBox(width: 10), + Container(color: bgColor, width: 40, height: 13), + ], + ), + const SizedBox(height: 6), + Container( + color: bgColor, + width: 100, + height: 13, + ), + ], + ), + ), + ], + )); + } +} diff --git a/lib/pages/search_panel/controller.dart b/lib/pages/search_panel/controller.dart index 2d1aa228..0307581d 100644 --- a/lib/pages/search_panel/controller.dart +++ b/lib/pages/search_panel/controller.dart @@ -31,7 +31,7 @@ class SearchPanelController extends GetxController { tids: searchType!.type != 'video' ? null : tids.value, ); if (result['status']) { - if (type == 'onRefresh') { + if (type == 'init') { resultList.value = result['data'].list ?? []; } else { resultList.addAll(result['data'].list ?? []); @@ -44,7 +44,7 @@ class SearchPanelController extends GetxController { Future onRefresh() async { page.value = 1; - await onSearch(type: 'onRefresh'); + await onSearch(); } // 返回顶部并刷新 diff --git a/lib/pages/search_panel/view.dart b/lib/pages/search_panel/view.dart index f032b12b..6d9a9535 100644 --- a/lib/pages/search_panel/view.dart +++ b/lib/pages/search_panel/view.dart @@ -4,6 +4,7 @@ import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/skeleton/media_bangumi.dart'; +import 'package:pilipala/common/skeleton/user_list.dart'; import 'package:pilipala/common/skeleton/video_card_h.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/models/common/search_type.dart'; @@ -81,11 +82,11 @@ class _SearchPanelState extends State future: _futureBuilderFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.data != null) { - Map data = snapshot.data; + Map? data = snapshot.data; + if (data != null && data['status']) { var ctr = _searchPanelController; RxList list = ctr.resultList; - if (data['status']) { + if (list.isNotEmpty) { return Obx(() { switch (widget.searchType) { case SearchType.video: @@ -110,21 +111,18 @@ class _SearchPanelState extends State }); } else { return HttpError( - errMsg: data['msg'], - fn: () { - setState(() { - _searchPanelController.onSearch(); - }); - }, + errMsg: '没有数据', + isShowBtn: false, + fn: () => {}, isInSliver: false, ); } } else { return HttpError( - errMsg: '没有相关数据', + errMsg: data?['msg'] ?? '请求异常', fn: () { setState(() { - _searchPanelController.onSearch(); + _futureBuilderFuture = _searchPanelController.onRefresh(); }); }, isInSliver: false, @@ -143,7 +141,7 @@ class _SearchPanelState extends State case SearchType.media_bangumi: return const MediaBangumiSkeleton(); case SearchType.bili_user: - return const VideoCardHSkeleton(); + return const UserListSkeleton(); case SearchType.live_room: return const VideoCardHSkeleton(); default: diff --git a/lib/pages/search_panel/widgets/media_bangumi_panel.dart b/lib/pages/search_panel/widgets/media_bangumi_panel.dart index 5bba0ab8..0a3704bb 100644 --- a/lib/pages/search_panel/widgets/media_bangumi_panel.dart +++ b/lib/pages/search_panel/widgets/media_bangumi_panel.dart @@ -1,12 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/badge.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; -import 'package:pilipala/http/search.dart'; -import 'package:pilipala/models/bangumi/info.dart'; -import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/utils.dart'; @@ -30,8 +25,8 @@ Widget searchMbangumiPanel(BuildContext context, ctr, list) { // }); }, child: Padding( - padding: const EdgeInsets.fromLTRB( - StyleString.safeSpace, 7, StyleString.safeSpace, 7), + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, vertical: 7), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/pages/search_panel/widgets/user_panel.dart b/lib/pages/search_panel/widgets/user_panel.dart index 918082bc..540ac043 100644 --- a/lib/pages/search_panel/widgets/user_panel.dart +++ b/lib/pages/search_panel/widgets/user_panel.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/utils/utils.dart'; @@ -20,7 +21,8 @@ Widget searchUserPanel(BuildContext context, ctr, list) { onTap: () => Get.toNamed('/member?mid=${i.mid}', arguments: {'heroTag': heroTag, 'face': i.upic}), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, vertical: 7), child: Row( children: [ Hero( diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index 96fdd91d..9056905f 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -3,6 +3,7 @@ import 'package:get/get.dart'; import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/pages/search_panel/index.dart'; import 'controller.dart'; +import 'widget/tab_bar.dart'; class SearchResultPage extends StatefulWidget { const SearchResultPage({super.key}); @@ -29,6 +30,17 @@ class _SearchResultPageState extends State ); } + // tab点击事件 + void _onTap(int index) { + if (index == _searchResultController.tabIndex) { + Get.find( + tag: SearchType.values[index].type + + _searchResultController.keyword!) + .animateToTop(); + } + _searchResultController.tabIndex = index; + } + @override Widget build(BuildContext context) { return Scaffold( @@ -55,50 +67,10 @@ class _SearchResultPageState extends State body: Column( children: [ const SizedBox(height: 4), - Container( - width: double.infinity, - padding: const EdgeInsets.only(left: 8), - color: Theme.of(context).colorScheme.surface, - child: Theme( - data: ThemeData( - splashColor: Colors.transparent, // 点击时的水波纹颜色设置为透明 - highlightColor: Colors.transparent, // 点击时的背景高亮颜色设置为透明 - ), - child: Obx( - () => (TabBar( - controller: _tabController, - tabs: [ - for (var i in _searchResultController.searchTabs) - Tab(text: "${i['label']} ${i['count'] ?? ''}") - ], - isScrollable: true, - indicatorWeight: 0, - indicatorPadding: - const EdgeInsets.symmetric(horizontal: 3, vertical: 8), - indicator: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, - borderRadius: const BorderRadius.all(Radius.circular(20)), - ), - indicatorSize: TabBarIndicatorSize.tab, - labelColor: - Theme.of(context).colorScheme.onSecondaryContainer, - labelStyle: const TextStyle(fontSize: 13), - dividerColor: Colors.transparent, - unselectedLabelColor: Theme.of(context).colorScheme.outline, - tabAlignment: TabAlignment.start, - onTap: (index) { - if (index == _searchResultController.tabIndex) { - Get.find( - tag: SearchType.values[index].type + - _searchResultController.keyword!) - .animateToTop(); - } - - _searchResultController.tabIndex = index; - }, - )), - ), - ), + TabBarWidget( + onTap: _onTap, + tabController: _tabController!, + searchResultCtr: _searchResultController, ), Expanded( child: TabBarView( diff --git a/lib/pages/search_result/widget/tab_bar.dart b/lib/pages/search_result/widget/tab_bar.dart new file mode 100644 index 00000000..acb6a3de --- /dev/null +++ b/lib/pages/search_result/widget/tab_bar.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pilipala/pages/search_result/index.dart'; + +class TabBarWidget extends StatelessWidget { + final Function(int) onTap; + final TabController tabController; + final SearchResultController searchResultCtr; + + const TabBarWidget({ + required this.onTap, + required this.tabController, + required this.searchResultCtr, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + ColorScheme colorScheme = Theme.of(context).colorScheme; + Color transparent = Colors.transparent; + return Container( + width: double.infinity, + padding: const EdgeInsets.only(left: 8), + color: colorScheme.surface, + child: Theme( + data: ThemeData(splashColor: transparent, highlightColor: transparent), + child: Obx( + () => TabBar( + controller: tabController, + tabs: [ + for (var i in searchResultCtr.searchTabs) + Tab(text: "${i['label']} ${i['count'] ?? ''}"), + ], + isScrollable: true, + indicatorPadding: + const EdgeInsets.symmetric(horizontal: 3, vertical: 8), + indicator: BoxDecoration( + color: colorScheme.secondaryContainer, + borderRadius: const BorderRadius.all(Radius.circular(20)), + ), + indicatorSize: TabBarIndicatorSize.tab, + labelColor: colorScheme.onSecondaryContainer, + labelStyle: const TextStyle(fontSize: 13), + dividerColor: transparent, + unselectedLabelColor: colorScheme.outline, + tabAlignment: TabAlignment.start, + onTap: onTap, + ), + ), + ), + ); + } +}