From 283262c58eeeab9df39ce89819a47e1f992cf3b0 Mon Sep 17 00:00:00 2001 From: orz12 Date: Fri, 26 Jan 2024 23:08:29 +0800 Subject: [PATCH] =?UTF-8?q?mod:=20=E4=B8=8D=E4=BD=BF=E7=94=A8FixedCrossAxi?= =?UTF-8?q?sCount=EF=BC=8C=E6=94=B9=E4=B8=BAMaxCrossAxisExtent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/video_card_v.dart | 49 +++------------------------ lib/pages/bangumi/view.dart | 18 +++++----- lib/pages/hot/view.dart | 13 ++++++- lib/pages/live/controller.dart | 2 -- lib/pages/live/view.dart | 24 ++++--------- lib/pages/live/widgets/live_item.dart | 35 +++---------------- lib/pages/rcmd/controller.dart | 2 -- lib/pages/rcmd/view.dart | 36 ++++++++------------ lib/pages/setting/style_setting.dart | 33 ++++++++++-------- lib/utils/grid.dart | 12 +++++++ lib/utils/storage.dart | 2 +- 11 files changed, 83 insertions(+), 143 deletions(-) create mode 100644 lib/utils/grid.dart diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index bfd11ce7..efd74d52 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -17,14 +17,12 @@ import 'video_popup_menu.dart'; // 视频卡片 - 垂直布局 class VideoCardV extends StatelessWidget { final dynamic videoItem; - final int crossAxisCount; final Function()? longPress; final Function()? longPressEnd; const VideoCardV({ Key? key, required this.videoItem, - required this.crossAxisCount, this.longPress, this.longPressEnd, }) : super(key: key); @@ -161,13 +159,6 @@ class VideoCardV extends StatelessWidget { ), ), if (videoItem.duration > 0) - if (crossAxisCount == 1) ...[ - PBadge( - bottom: 10, - right: 10, - text: Utils.timeFormat(videoItem.duration), - ) - ] else ...[ PBadge( bottom: 6, right: 7, @@ -175,12 +166,11 @@ class VideoCardV extends StatelessWidget { type: 'gray', text: Utils.timeFormat(videoItem.duration), ) - ], ], ); }), ), - VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) + VideoContent(videoItem: videoItem) ], ), ), @@ -191,18 +181,14 @@ class VideoCardV extends StatelessWidget { class VideoContent extends StatelessWidget { final dynamic videoItem; - final int crossAxisCount; const VideoContent( - {Key? key, required this.videoItem, required this.crossAxisCount}) + {Key? key, required this.videoItem}) : super(key: key); @override Widget build(BuildContext context) { return Expanded( - flex: crossAxisCount == 1 ? 0 : 1, child: Padding( - padding: crossAxisCount == 1 - ? const EdgeInsets.fromLTRB(9, 9, 9, 4) - : const EdgeInsets.fromLTRB(5, 8, 5, 4), + padding: const EdgeInsets.fromLTRB(5, 8, 5, 4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, // mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -216,23 +202,12 @@ class VideoContent extends StatelessWidget { overflow: TextOverflow.ellipsis, ), ), - if (videoItem.goto == 'av' && crossAxisCount == 1) ...[ - const SizedBox(width: 10), - VideoPopupMenu( - size: 32, - iconSize: 18, - videoItem: videoItem, - ), - ], ], ), - if (crossAxisCount > 1) ...[ const SizedBox(height: 2), VideoStat( videoItem: videoItem, ), - ], - if (crossAxisCount == 1) const SizedBox(height: 4), Row( children: [ if (videoItem.goto == 'bangumi') ...[ @@ -271,7 +246,7 @@ class VideoContent extends StatelessWidget { ) ], Expanded( - flex: crossAxisCount == 1 ? 0 : 1, + flex: 1, child: Text( videoItem.owner.name, maxLines: 1, @@ -282,21 +257,7 @@ class VideoContent extends StatelessWidget { ), ), ), - if (crossAxisCount == 1) ...[ - Text( - ' • ', - style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - VideoStat( - videoItem: videoItem, - ), - const Spacer(), - ], - if (videoItem.goto == 'av' && crossAxisCount != 1) ...[ + if (videoItem.goto == 'av') ...[ VideoPopupMenu( size: 24, iconSize: 14, diff --git a/lib/pages/bangumi/view.dart b/lib/pages/bangumi/view.dart index 560f09a5..8ceb5fbe 100644 --- a/lib/pages/bangumi/view.dart +++ b/lib/pages/bangumi/view.dart @@ -11,6 +11,7 @@ import 'package:pilipala/pages/home/index.dart'; import 'package:pilipala/pages/main/index.dart'; import 'package:pilipala/pages/rcmd/view.dart'; +import '../../utils/grid.dart'; import 'controller.dart'; import 'widgets/bangumu_card_v.dart'; @@ -215,16 +216,17 @@ class _BangumiPageState extends State } Widget contentGrid(ctr, bangumiList) { + return SliverGrid( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( // 行间距 - mainAxisSpacing: StyleString.cardSpace - 2, - // 列间距 - crossAxisSpacing: StyleString.cardSpace, - // 列数 - crossAxisCount: 3, - mainAxisExtent: Get.size.width / 3 / 0.65 + - MediaQuery.textScalerOf(context).scale(32.0), + mainAxisSpacing: StyleString.cardSpace - 2, + // 列间距 + crossAxisSpacing: StyleString.cardSpace, + // 最大宽度 + maxCrossAxisExtent: Grid.maxRowWidth / 3 * 2, + mainAxisExtent: Grid.calculateActualWidth(context, Grid.maxRowWidth / 3 * 2, StyleString.safeSpace) / 0.65+ + MediaQuery.textScalerOf(context).scale(60), ), delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { diff --git a/lib/pages/hot/view.dart b/lib/pages/hot/view.dart index 2673e84c..c94d6785 100644 --- a/lib/pages/hot/view.dart +++ b/lib/pages/hot/view.dart @@ -13,6 +13,8 @@ import 'package:pilipala/pages/home/index.dart'; import 'package:pilipala/pages/hot/controller.dart'; import 'package:pilipala/pages/main/index.dart'; +import '../../utils/grid.dart'; + class HotPage extends StatefulWidget { const HotPage({Key? key}) : super(key: key); @@ -88,7 +90,16 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { Map data = snapshot.data as Map; if (data['status']) { return Obx( - () => SliverList( + () => SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + // 行间距 + mainAxisSpacing: StyleString.safeSpace, + // 列间距 + crossAxisSpacing: StyleString.safeSpace, + // 最大宽度 + maxCrossAxisExtent: Grid.maxRowWidth * 2, + mainAxisExtent: Grid.calculateActualWidth(context, Grid.maxRowWidth * 2, StyleString.safeSpace) / 1.9 / StyleString.aspectRatio + ), delegate: SliverChildBuilderDelegate((context, index) { return VideoCardH( diff --git a/lib/pages/live/controller.dart b/lib/pages/live/controller.dart index 6a26f0d2..a34b8ae9 100644 --- a/lib/pages/live/controller.dart +++ b/lib/pages/live/controller.dart @@ -19,8 +19,6 @@ class LiveController extends GetxController { @override void onInit() { super.onInit(); - crossAxisCount.value = - setting.get(SettingBoxKey.customRows, defaultValue: 2); } // 获取推荐 diff --git a/lib/pages/live/view.dart b/lib/pages/live/view.dart index f693acf1..a26b6390 100644 --- a/lib/pages/live/view.dart +++ b/lib/pages/live/view.dart @@ -13,6 +13,7 @@ import 'package:pilipala/pages/home/index.dart'; import 'package:pilipala/pages/main/index.dart'; import 'package:pilipala/pages/rcmd/index.dart'; +import '../../utils/grid.dart'; import 'controller.dart'; import 'widgets/live_item.dart'; @@ -143,35 +144,22 @@ class _LivePageState extends State } Widget contentGrid(ctr, liveList) { - // double maxWidth = Get.size.width; - // int baseWidth = 500; - // int step = 300; - // int crossAxisCount = - // maxWidth > baseWidth ? 2 + ((maxWidth - baseWidth) / step).ceil() : 2; - // if (maxWidth < 300) { - // crossAxisCount = 1; - // } - int crossAxisCount = ctr.crossAxisCount.value; return SliverGrid( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( // 行间距 mainAxisSpacing: StyleString.safeSpace, // 列间距 crossAxisSpacing: StyleString.safeSpace, - // 列数 - crossAxisCount: crossAxisCount, - mainAxisExtent: - Get.size.width / crossAxisCount / StyleString.aspectRatio + - MediaQuery.textScalerOf(context).scale( - (crossAxisCount == 1 ? 48 : 68), - ), + // 最大宽度 + maxCrossAxisExtent: Grid.maxRowWidth, + mainAxisExtent: Grid.calculateActualWidth(context, Grid.maxRowWidth, StyleString.safeSpace) / StyleString.aspectRatio+ + MediaQuery.textScalerOf(context).scale(80), ), delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return liveList!.isNotEmpty ? LiveCardV( liveItem: liveList[index], - crossAxisCount: crossAxisCount, longPress: () { _liveController.popupDialog = _createPopupDialog(liveList[index]); diff --git a/lib/pages/live/widgets/live_item.dart b/lib/pages/live/widgets/live_item.dart index 8fa797fb..f313e0f7 100644 --- a/lib/pages/live/widgets/live_item.dart +++ b/lib/pages/live/widgets/live_item.dart @@ -8,14 +8,12 @@ import 'package:pilipala/common/widgets/network_img_layer.dart'; // 视频卡片 - 垂直布局 class LiveCardV extends StatelessWidget { final LiveItemModel liveItem; - final int crossAxisCount; final Function()? longPress; final Function()? longPressEnd; const LiveCardV({ Key? key, required this.liveItem, - required this.crossAxisCount, this.longPress, this.longPressEnd, }) : super(key: key); @@ -62,7 +60,6 @@ class LiveCardV extends StatelessWidget { height: maxHeight, ), ), - if (crossAxisCount != 1) Positioned( left: 0, right: 0, @@ -80,7 +77,7 @@ class LiveCardV extends StatelessWidget { }), ), ), - LiveContent(liveItem: liveItem, crossAxisCount: crossAxisCount) + LiveContent(liveItem: liveItem) ], ), ), @@ -91,18 +88,15 @@ class LiveCardV extends StatelessWidget { class LiveContent extends StatelessWidget { final dynamic liveItem; - final int crossAxisCount; const LiveContent( - {Key? key, required this.liveItem, required this.crossAxisCount}) + {Key? key, required this.liveItem}) : super(key: key); @override Widget build(BuildContext context) { return Expanded( - flex: crossAxisCount == 1 ? 0 : 1, + flex: 1, child: Padding( - padding: crossAxisCount == 1 - ? const EdgeInsets.fromLTRB(9, 9, 9, 4) - : const EdgeInsets.fromLTRB(5, 8, 5, 4), + padding: const EdgeInsets.fromLTRB(5, 8, 5, 4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -114,10 +108,9 @@ class LiveContent extends StatelessWidget { fontWeight: FontWeight.w500, letterSpacing: 0.3, ), - maxLines: crossAxisCount == 1 ? 1 : 2, + maxLines: 2, overflow: TextOverflow.ellipsis, ), - if (crossAxisCount == 1) const SizedBox(height: 4), Row( children: [ Expanded( @@ -133,24 +126,6 @@ class LiveContent extends StatelessWidget { overflow: TextOverflow.ellipsis, ), ), - if (crossAxisCount == 1) ...[ - Text( - ' • ${liveItem!.areaName!}', - style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - Text( - ' • ${liveItem!.watchedShow!['text_small']}人观看', - style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - ] ], ), ], diff --git a/lib/pages/rcmd/controller.dart b/lib/pages/rcmd/controller.dart index 54cb8c14..3e031e69 100644 --- a/lib/pages/rcmd/controller.dart +++ b/lib/pages/rcmd/controller.dart @@ -23,8 +23,6 @@ class RcmdController extends GetxController { @override void onInit() { super.onInit(); - crossAxisCount.value = - setting.get(SettingBoxKey.customRows, defaultValue: 2); // 读取app端缓存内容 // if (recVideo.get('cacheList') != null && // recVideo.get('cacheList').isNotEmpty) { diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index 687eacd1..ce5996f8 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -13,6 +13,7 @@ import 'package:pilipala/common/widgets/video_card_v.dart'; import 'package:pilipala/pages/home/index.dart'; import 'package:pilipala/pages/main/index.dart'; +import '../../utils/grid.dart'; import 'controller.dart'; class RcmdPage extends StatefulWidget { @@ -88,9 +89,11 @@ class _RcmdPageState extends State slivers: [ SliverPadding( padding: - const EdgeInsets.fromLTRB(0, StyleString.safeSpace, 0, 0), - sliver: Obx(() { // 使用Obx来监听数据的变化 - if (_rcmdController.isLoadingMore && _rcmdController.videoList.isEmpty) { + const EdgeInsets.fromLTRB(0, StyleString.safeSpace, 0, 0), + sliver: Obx(() { + // 使用Obx来监听数据的变化 + if (_rcmdController.isLoadingMore && + _rcmdController.videoList.isEmpty) { return contentGrid(_rcmdController, []); // 如果正在加载并且列表为空,则显示加载指示器 // return const SliverToBoxAdapter( @@ -98,7 +101,8 @@ class _RcmdPageState extends State // ); } else { // 显示视频列表 - return contentGrid(_rcmdController, _rcmdController.videoList); + return contentGrid( + _rcmdController, _rcmdController.videoList); } }), ), @@ -120,35 +124,23 @@ class _RcmdPageState extends State } Widget contentGrid(ctr, videoList) { - // double maxWidth = Get.size.width; - // int baseWidth = 500; - // int step = 300; - // int crossAxisCount = - // maxWidth > baseWidth ? 2 + ((maxWidth - baseWidth) / step).ceil() : 2; - // if (maxWidth < 300) { - // crossAxisCount = 1; - // } - int crossAxisCount = ctr.crossAxisCount.value; - double mainAxisExtent = (Get.size.width / - crossAxisCount / - StyleString.aspectRatio) + - (crossAxisCount == 1 ? 68 : MediaQuery.textScalerOf(context).scale(86)); + return SliverGrid( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( // 行间距 mainAxisSpacing: StyleString.safeSpace, // 列间距 crossAxisSpacing: StyleString.safeSpace, - // 列数 - crossAxisCount: crossAxisCount, - mainAxisExtent: mainAxisExtent, + // 最大宽度 + maxCrossAxisExtent: Grid.maxRowWidth, + mainAxisExtent: Grid.calculateActualWidth(context, Grid.maxRowWidth, StyleString.safeSpace) / StyleString.aspectRatio+ + MediaQuery.textScalerOf(context).scale(96), ), delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return videoList!.isNotEmpty ? VideoCardV( videoItem: videoList[index], - crossAxisCount: crossAxisCount, longPress: () { _rcmdController.popupDialog = _createPopupDialog(videoList[index]); diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index 57ec110a..df1df9c0 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -29,7 +29,7 @@ class _StyleSettingState extends State { late int picQuality; late double toastOpacity; late ThemeType _tempThemeValue; - late dynamic defaultCustomRows; + late double maxRowWidth; @override void initState() { @@ -37,7 +37,7 @@ class _StyleSettingState extends State { picQuality = setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10); toastOpacity = setting.get(SettingBoxKey.defaultToastOp, defaultValue: 1.0); _tempThemeValue = settingController.themeType.value; - defaultCustomRows = setting.get(SettingBoxKey.customRows, defaultValue: 2); + maxRowWidth = setting.get(SettingBoxKey.maxRowWidth, defaultValue: 240.0) as double; } @override @@ -83,7 +83,7 @@ class _StyleSettingState extends State { ), const SetSwitchItem( title: 'MD3样式底栏', - subTitle: '符合Material You设计规范的底栏', + subTitle: '符合Material You设计规范的底栏,关闭可使底栏变窄', setKey: SettingBoxKey.enableMYBar, defaultVal: true, ), @@ -103,27 +103,30 @@ class _StyleSettingState extends State { ), ListTile( onTap: () async { - int? result = await showDialog( + double? result = await showDialog( context: context, builder: (context) { - return SelectDialog( - title: '自定义列数', - value: defaultCustomRows, - values: [1, 2, 3, 4, 5].map((e) { - return {'title': '$e 列', 'value': e}; - }).toList()); - }, + return SlideDialog( + title: '最大列宽度(默认240dp)', + value: maxRowWidth, + min: 150.0, + max: 500.0, + divisions: 35, + suffix: 'dp', + ); + } ); if (result != null) { - defaultCustomRows = result; - setting.put(SettingBoxKey.customRows, result); + maxRowWidth = result; + setting.put(SettingBoxKey.maxRowWidth, result); + SmartDialog.showToast('重启生效'); setState(() {}); } }, dense: false, - title: Text('自定义列数', style: titleStyle), + title: Text('最大列宽度(dp)', style: titleStyle), subtitle: Text( - '当前列数 $defaultCustomRows 列', + '当前最大列宽度:${maxRowWidth.toInt()}dp,屏幕宽度:${MediaQuery.of(context).size.width.toPrecision(2)}dp,', style: subTitleStyle, ), ), diff --git a/lib/utils/grid.dart b/lib/utils/grid.dart new file mode 100644 index 00000000..bbe72772 --- /dev/null +++ b/lib/utils/grid.dart @@ -0,0 +1,12 @@ +import 'package:flutter/cupertino.dart'; +import 'storage.dart'; +class Grid { + static double maxRowWidth = GStrorage.setting.get(SettingBoxKey.maxRowWidth, defaultValue: 240.0) as double; + + static double calculateActualWidth(BuildContext context, double maxCrossAxisExtent, double crossAxisSpacing) { + double screenWidth = MediaQuery.of(context).size.width; + int columnCount = ((screenWidth - crossAxisSpacing) / (maxCrossAxisExtent + crossAxisSpacing)).ceil(); + double columnWidth = (screenWidth - crossAxisSpacing) ~/ columnCount - crossAxisSpacing; + return columnWidth; + } +} diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index e5b03030..fb9bc180 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -149,7 +149,7 @@ class SettingBoxKey { customColor = 'customColor', // 自定义主题色 enableSingleRow = 'enableSingleRow', // 首页单列 displayMode = 'displayMode', - customRows = 'customRows', // 自定义列 + maxRowWidth = 'maxRowWidth', // 首页列最大宽度(dp) enableMYBar = 'enableMYBar', hideSearchBar = 'hideSearchBar', // 收起顶栏 hideTabBar = 'hideTabBar', // 收起底栏