mod: 不使用FixedCrossAxisCount,改为MaxCrossAxisExtent

This commit is contained in:
orz12
2024-01-26 23:08:29 +08:00
parent bf6cef3a19
commit 283262c58e
11 changed files with 83 additions and 143 deletions

View File

@@ -17,14 +17,12 @@ import 'video_popup_menu.dart';
// 视频卡片 - 垂直布局 // 视频卡片 - 垂直布局
class VideoCardV extends StatelessWidget { class VideoCardV extends StatelessWidget {
final dynamic videoItem; final dynamic videoItem;
final int crossAxisCount;
final Function()? longPress; final Function()? longPress;
final Function()? longPressEnd; final Function()? longPressEnd;
const VideoCardV({ const VideoCardV({
Key? key, Key? key,
required this.videoItem, required this.videoItem,
required this.crossAxisCount,
this.longPress, this.longPress,
this.longPressEnd, this.longPressEnd,
}) : super(key: key); }) : super(key: key);
@@ -161,13 +159,6 @@ class VideoCardV extends StatelessWidget {
), ),
), ),
if (videoItem.duration > 0) if (videoItem.duration > 0)
if (crossAxisCount == 1) ...[
PBadge(
bottom: 10,
right: 10,
text: Utils.timeFormat(videoItem.duration),
)
] else ...[
PBadge( PBadge(
bottom: 6, bottom: 6,
right: 7, right: 7,
@@ -176,11 +167,10 @@ class VideoCardV extends StatelessWidget {
text: Utils.timeFormat(videoItem.duration), 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 { class VideoContent extends StatelessWidget {
final dynamic videoItem; final dynamic videoItem;
final int crossAxisCount;
const VideoContent( const VideoContent(
{Key? key, required this.videoItem, required this.crossAxisCount}) {Key? key, required this.videoItem})
: super(key: key); : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Expanded( return Expanded(
flex: crossAxisCount == 1 ? 0 : 1,
child: Padding( child: Padding(
padding: crossAxisCount == 1 padding: const EdgeInsets.fromLTRB(5, 8, 5, 4),
? const EdgeInsets.fromLTRB(9, 9, 9, 4)
: const EdgeInsets.fromLTRB(5, 8, 5, 4),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -216,23 +202,12 @@ class VideoContent extends StatelessWidget {
overflow: TextOverflow.ellipsis, 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), const SizedBox(height: 2),
VideoStat( VideoStat(
videoItem: videoItem, videoItem: videoItem,
), ),
],
if (crossAxisCount == 1) const SizedBox(height: 4),
Row( Row(
children: [ children: [
if (videoItem.goto == 'bangumi') ...[ if (videoItem.goto == 'bangumi') ...[
@@ -271,7 +246,7 @@ class VideoContent extends StatelessWidget {
) )
], ],
Expanded( Expanded(
flex: crossAxisCount == 1 ? 0 : 1, flex: 1,
child: Text( child: Text(
videoItem.owner.name, videoItem.owner.name,
maxLines: 1, maxLines: 1,
@@ -282,21 +257,7 @@ class VideoContent extends StatelessWidget {
), ),
), ),
), ),
if (crossAxisCount == 1) ...[ if (videoItem.goto == 'av') ...[
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) ...[
VideoPopupMenu( VideoPopupMenu(
size: 24, size: 24,
iconSize: 14, iconSize: 14,

View File

@@ -11,6 +11,7 @@ import 'package:pilipala/pages/home/index.dart';
import 'package:pilipala/pages/main/index.dart'; import 'package:pilipala/pages/main/index.dart';
import 'package:pilipala/pages/rcmd/view.dart'; import 'package:pilipala/pages/rcmd/view.dart';
import '../../utils/grid.dart';
import 'controller.dart'; import 'controller.dart';
import 'widgets/bangumu_card_v.dart'; import 'widgets/bangumu_card_v.dart';
@@ -215,16 +216,17 @@ class _BangumiPageState extends State<BangumiPage>
} }
Widget contentGrid(ctr, bangumiList) { Widget contentGrid(ctr, bangumiList) {
return SliverGrid( return SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
// 行间距 // 行间距
mainAxisSpacing: StyleString.cardSpace - 2, mainAxisSpacing: StyleString.cardSpace - 2,
// 列间距 // 列间距
crossAxisSpacing: StyleString.cardSpace, crossAxisSpacing: StyleString.cardSpace,
// 列数 // 最大宽度
crossAxisCount: 3, maxCrossAxisExtent: Grid.maxRowWidth / 3 * 2,
mainAxisExtent: Get.size.width / 3 / 0.65 + mainAxisExtent: Grid.calculateActualWidth(context, Grid.maxRowWidth / 3 * 2, StyleString.safeSpace) / 0.65+
MediaQuery.textScalerOf(context).scale(32.0), MediaQuery.textScalerOf(context).scale(60),
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (BuildContext context, int index) {

View File

@@ -13,6 +13,8 @@ import 'package:pilipala/pages/home/index.dart';
import 'package:pilipala/pages/hot/controller.dart'; import 'package:pilipala/pages/hot/controller.dart';
import 'package:pilipala/pages/main/index.dart'; import 'package:pilipala/pages/main/index.dart';
import '../../utils/grid.dart';
class HotPage extends StatefulWidget { class HotPage extends StatefulWidget {
const HotPage({Key? key}) : super(key: key); const HotPage({Key? key}) : super(key: key);
@@ -88,7 +90,16 @@ class _HotPageState extends State<HotPage> with AutomaticKeepAliveClientMixin {
Map data = snapshot.data as Map; Map data = snapshot.data as Map;
if (data['status']) { if (data['status']) {
return Obx( 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: delegate:
SliverChildBuilderDelegate((context, index) { SliverChildBuilderDelegate((context, index) {
return VideoCardH( return VideoCardH(

View File

@@ -19,8 +19,6 @@ class LiveController extends GetxController {
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
crossAxisCount.value =
setting.get(SettingBoxKey.customRows, defaultValue: 2);
} }
// 获取推荐 // 获取推荐

View File

@@ -13,6 +13,7 @@ import 'package:pilipala/pages/home/index.dart';
import 'package:pilipala/pages/main/index.dart'; import 'package:pilipala/pages/main/index.dart';
import 'package:pilipala/pages/rcmd/index.dart'; import 'package:pilipala/pages/rcmd/index.dart';
import '../../utils/grid.dart';
import 'controller.dart'; import 'controller.dart';
import 'widgets/live_item.dart'; import 'widgets/live_item.dart';
@@ -143,35 +144,22 @@ class _LivePageState extends State<LivePage>
} }
Widget contentGrid(ctr, liveList) { 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( return SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
// 行间距 // 行间距
mainAxisSpacing: StyleString.safeSpace, mainAxisSpacing: StyleString.safeSpace,
// 列间距 // 列间距
crossAxisSpacing: StyleString.safeSpace, crossAxisSpacing: StyleString.safeSpace,
// 列数 // 最大宽度
crossAxisCount: crossAxisCount, maxCrossAxisExtent: Grid.maxRowWidth,
mainAxisExtent: mainAxisExtent: Grid.calculateActualWidth(context, Grid.maxRowWidth, StyleString.safeSpace) / StyleString.aspectRatio+
Get.size.width / crossAxisCount / StyleString.aspectRatio + MediaQuery.textScalerOf(context).scale(80),
MediaQuery.textScalerOf(context).scale(
(crossAxisCount == 1 ? 48 : 68),
),
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (BuildContext context, int index) {
return liveList!.isNotEmpty return liveList!.isNotEmpty
? LiveCardV( ? LiveCardV(
liveItem: liveList[index], liveItem: liveList[index],
crossAxisCount: crossAxisCount,
longPress: () { longPress: () {
_liveController.popupDialog = _liveController.popupDialog =
_createPopupDialog(liveList[index]); _createPopupDialog(liveList[index]);

View File

@@ -8,14 +8,12 @@ import 'package:pilipala/common/widgets/network_img_layer.dart';
// 视频卡片 - 垂直布局 // 视频卡片 - 垂直布局
class LiveCardV extends StatelessWidget { class LiveCardV extends StatelessWidget {
final LiveItemModel liveItem; final LiveItemModel liveItem;
final int crossAxisCount;
final Function()? longPress; final Function()? longPress;
final Function()? longPressEnd; final Function()? longPressEnd;
const LiveCardV({ const LiveCardV({
Key? key, Key? key,
required this.liveItem, required this.liveItem,
required this.crossAxisCount,
this.longPress, this.longPress,
this.longPressEnd, this.longPressEnd,
}) : super(key: key); }) : super(key: key);
@@ -62,7 +60,6 @@ class LiveCardV extends StatelessWidget {
height: maxHeight, height: maxHeight,
), ),
), ),
if (crossAxisCount != 1)
Positioned( Positioned(
left: 0, left: 0,
right: 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 { class LiveContent extends StatelessWidget {
final dynamic liveItem; final dynamic liveItem;
final int crossAxisCount;
const LiveContent( const LiveContent(
{Key? key, required this.liveItem, required this.crossAxisCount}) {Key? key, required this.liveItem})
: super(key: key); : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Expanded( return Expanded(
flex: crossAxisCount == 1 ? 0 : 1, flex: 1,
child: Padding( child: Padding(
padding: crossAxisCount == 1 padding: const EdgeInsets.fromLTRB(5, 8, 5, 4),
? const EdgeInsets.fromLTRB(9, 9, 9, 4)
: const EdgeInsets.fromLTRB(5, 8, 5, 4),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -114,10 +108,9 @@ class LiveContent extends StatelessWidget {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
letterSpacing: 0.3, letterSpacing: 0.3,
), ),
maxLines: crossAxisCount == 1 ? 1 : 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
if (crossAxisCount == 1) const SizedBox(height: 4),
Row( Row(
children: [ children: [
Expanded( Expanded(
@@ -133,24 +126,6 @@ class LiveContent extends StatelessWidget {
overflow: TextOverflow.ellipsis, 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,
),
),
]
], ],
), ),
], ],

View File

@@ -23,8 +23,6 @@ class RcmdController extends GetxController {
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
crossAxisCount.value =
setting.get(SettingBoxKey.customRows, defaultValue: 2);
// 读取app端缓存内容 // 读取app端缓存内容
// if (recVideo.get('cacheList') != null && // if (recVideo.get('cacheList') != null &&
// recVideo.get('cacheList').isNotEmpty) { // recVideo.get('cacheList').isNotEmpty) {

View File

@@ -13,6 +13,7 @@ import 'package:pilipala/common/widgets/video_card_v.dart';
import 'package:pilipala/pages/home/index.dart'; import 'package:pilipala/pages/home/index.dart';
import 'package:pilipala/pages/main/index.dart'; import 'package:pilipala/pages/main/index.dart';
import '../../utils/grid.dart';
import 'controller.dart'; import 'controller.dart';
class RcmdPage extends StatefulWidget { class RcmdPage extends StatefulWidget {
@@ -89,8 +90,10 @@ class _RcmdPageState extends State<RcmdPage>
SliverPadding( SliverPadding(
padding: padding:
const EdgeInsets.fromLTRB(0, StyleString.safeSpace, 0, 0), const EdgeInsets.fromLTRB(0, StyleString.safeSpace, 0, 0),
sliver: Obx(() { // 使用Obx来监听数据的变化 sliver: Obx(() {
if (_rcmdController.isLoadingMore && _rcmdController.videoList.isEmpty) { // 使用Obx来监听数据的变化
if (_rcmdController.isLoadingMore &&
_rcmdController.videoList.isEmpty) {
return contentGrid(_rcmdController, []); return contentGrid(_rcmdController, []);
// 如果正在加载并且列表为空,则显示加载指示器 // 如果正在加载并且列表为空,则显示加载指示器
// return const SliverToBoxAdapter( // return const SliverToBoxAdapter(
@@ -98,7 +101,8 @@ class _RcmdPageState extends State<RcmdPage>
// ); // );
} else { } else {
// 显示视频列表 // 显示视频列表
return contentGrid(_rcmdController, _rcmdController.videoList); return contentGrid(
_rcmdController, _rcmdController.videoList);
} }
}), }),
), ),
@@ -120,35 +124,23 @@ class _RcmdPageState extends State<RcmdPage>
} }
Widget contentGrid(ctr, videoList) { 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( return SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
// 行间距 // 行间距
mainAxisSpacing: StyleString.safeSpace, mainAxisSpacing: StyleString.safeSpace,
// 列间距 // 列间距
crossAxisSpacing: StyleString.safeSpace, crossAxisSpacing: StyleString.safeSpace,
// 列数 // 最大宽度
crossAxisCount: crossAxisCount, maxCrossAxisExtent: Grid.maxRowWidth,
mainAxisExtent: mainAxisExtent, mainAxisExtent: Grid.calculateActualWidth(context, Grid.maxRowWidth, StyleString.safeSpace) / StyleString.aspectRatio+
MediaQuery.textScalerOf(context).scale(96),
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (BuildContext context, int index) {
return videoList!.isNotEmpty return videoList!.isNotEmpty
? VideoCardV( ? VideoCardV(
videoItem: videoList[index], videoItem: videoList[index],
crossAxisCount: crossAxisCount,
longPress: () { longPress: () {
_rcmdController.popupDialog = _rcmdController.popupDialog =
_createPopupDialog(videoList[index]); _createPopupDialog(videoList[index]);

View File

@@ -29,7 +29,7 @@ class _StyleSettingState extends State<StyleSetting> {
late int picQuality; late int picQuality;
late double toastOpacity; late double toastOpacity;
late ThemeType _tempThemeValue; late ThemeType _tempThemeValue;
late dynamic defaultCustomRows; late double maxRowWidth;
@override @override
void initState() { void initState() {
@@ -37,7 +37,7 @@ class _StyleSettingState extends State<StyleSetting> {
picQuality = setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10); picQuality = setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10);
toastOpacity = setting.get(SettingBoxKey.defaultToastOp, defaultValue: 1.0); toastOpacity = setting.get(SettingBoxKey.defaultToastOp, defaultValue: 1.0);
_tempThemeValue = settingController.themeType.value; _tempThemeValue = settingController.themeType.value;
defaultCustomRows = setting.get(SettingBoxKey.customRows, defaultValue: 2); maxRowWidth = setting.get(SettingBoxKey.maxRowWidth, defaultValue: 240.0) as double;
} }
@override @override
@@ -83,7 +83,7 @@ class _StyleSettingState extends State<StyleSetting> {
), ),
const SetSwitchItem( const SetSwitchItem(
title: 'MD3样式底栏', title: 'MD3样式底栏',
subTitle: '符合Material You设计规范的底栏', subTitle: '符合Material You设计规范的底栏,关闭可使底栏变窄',
setKey: SettingBoxKey.enableMYBar, setKey: SettingBoxKey.enableMYBar,
defaultVal: true, defaultVal: true,
), ),
@@ -103,27 +103,30 @@ class _StyleSettingState extends State<StyleSetting> {
), ),
ListTile( ListTile(
onTap: () async { onTap: () async {
int? result = await showDialog( double? result = await showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
return SelectDialog<int>( return SlideDialog<double>(
title: '自定义列数', title: '最大列宽度默认240dp',
value: defaultCustomRows, value: maxRowWidth,
values: [1, 2, 3, 4, 5].map((e) { min: 150.0,
return {'title': '$e', 'value': e}; max: 500.0,
}).toList()); divisions: 35,
}, suffix: 'dp',
);
}
); );
if (result != null) { if (result != null) {
defaultCustomRows = result; maxRowWidth = result;
setting.put(SettingBoxKey.customRows, result); setting.put(SettingBoxKey.maxRowWidth, result);
SmartDialog.showToast('重启生效');
setState(() {}); setState(() {});
} }
}, },
dense: false, dense: false,
title: Text('自定义列数', style: titleStyle), title: Text('最大列宽度dp', style: titleStyle),
subtitle: Text( subtitle: Text(
'当前列数 $defaultCustomRows', '当前最大列宽度:${maxRowWidth.toInt()}dp屏幕宽度${MediaQuery.of(context).size.width.toPrecision(2)}dp',
style: subTitleStyle, style: subTitleStyle,
), ),
), ),

12
lib/utils/grid.dart Normal file
View File

@@ -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;
}
}

View File

@@ -149,7 +149,7 @@ class SettingBoxKey {
customColor = 'customColor', // 自定义主题色 customColor = 'customColor', // 自定义主题色
enableSingleRow = 'enableSingleRow', // 首页单列 enableSingleRow = 'enableSingleRow', // 首页单列
displayMode = 'displayMode', displayMode = 'displayMode',
customRows = 'customRows', // 自定义列 maxRowWidth = 'maxRowWidth', // 首页列最大宽度dp
enableMYBar = 'enableMYBar', enableMYBar = 'enableMYBar',
hideSearchBar = 'hideSearchBar', // 收起顶栏 hideSearchBar = 'hideSearchBar', // 收起顶栏
hideTabBar = 'hideTabBar', // 收起底栏 hideTabBar = 'hideTabBar', // 收起底栏