mod: 动态页面图片、合集渲染

This commit is contained in:
guozhigq
2023-06-25 00:24:27 +08:00
parent 714cbb2d0f
commit 936c5d235c
2 changed files with 177 additions and 10 deletions

View File

@ -198,11 +198,13 @@ class DynamicMajorModel {
DynamicMajorModel({
this.archive,
this.draw,
this.ugcSeason,
this.type,
});
DynamicArchiveModel? archive;
DynamicDrawModel? draw;
DynamicArchiveModel? ugcSeason;
DynamicOpusModel? opus;
// MAJOR_TYPE_DRAW 图片
// MAJOR_TYPE_ARCHIVE 视频
@ -215,6 +217,9 @@ class DynamicMajorModel {
: null;
draw =
json['draw'] != null ? DynamicDrawModel.fromJson(json['draw']) : null;
ugcSeason = json['ugc_season'] != null
? DynamicArchiveModel.fromJson(json['ugc_season'])
: null;
opus =
json['opus'] != null ? DynamicOpusModel.fromJson(json['opus']) : null;
type = json['type'];
@ -236,7 +241,7 @@ class DynamicArchiveModel {
this.type,
});
String? aid;
int? aid;
Map? badge;
String? bvid;
String? cover;
@ -249,14 +254,14 @@ class DynamicArchiveModel {
int? type;
DynamicArchiveModel.fromJson(Map<String, dynamic> json) {
aid = json['aid'];
aid = json['aid'] is String ? int.parse(json['aid']) : json['aid'];
badge = json['badge'];
bvid = json['bvid'];
cover = json['cover'];
disablePreview = json['disable_preview'];
durationText = json['duration_text'];
jumpUrl = json['jump_url'];
stat = Stat.fromJson(json['stat']);
stat = json['stat'] != null ? Stat.fromJson(json['stat']) : null;
title = json['title'];
type = json['type'];
}
@ -265,17 +270,17 @@ class DynamicArchiveModel {
class DynamicDrawModel {
DynamicDrawModel({
this.id,
this.item,
this.items,
});
int? id;
List<DynamicDrawItemModel>? item;
List<DynamicDrawItemModel>? items;
DynamicDrawModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
// ignore: prefer_null_aware_operators
item = json['item'] != null
? json['item']
items = json['items'] != null
? json['items']
.map<DynamicDrawItemModel>((e) => DynamicDrawItemModel.fromJson(e))
.toList()
: null;
@ -332,7 +337,7 @@ class DynamicDrawItemModel {
this.width,
});
int? height;
int? size;
double? size;
String? src;
List? tags;
int? width;

View File

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/common/widgets/stat/danmu.dart';
@ -99,7 +100,10 @@ class DynamicPanel extends StatelessWidget {
switch (item.type) {
// 图文
case 'DYNAMIC_TYPE_DRAW':
return const Text('DYNAMIC_TYPE_DRAW');
return Padding(
padding: const EdgeInsets.only(left: 6, right: 6),
child: picWidget(item, context),
);
// 视频
case 'DYNAMIC_TYPE_AV':
return Column(
@ -231,7 +235,112 @@ class DynamicPanel extends StatelessWidget {
return const Text('DYNAMIC_TYPE_LIVE_RCMD');
// 合集
case 'DYNAMIC_TYPE_UGC_SEASON':
return const Text('DYNAMIC_TYPE_UGC_SEASON');
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// if (floor == 2) ...[
// Text('@' + item.modules.moduleAuthor.name),
// const SizedBox(height: 8),
// ],
GestureDetector(
onTap: () {},
child: LayoutBuilder(builder: (context, box) {
double width = box.maxWidth;
return Stack(
children: [
NetworkImgLayer(
type: floor == 1 ? 'emote' : null,
width: width,
height: width / StyleString.aspectRatio,
src: item.modules.moduleDynamic.major.ugcSeason.cover,
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
padding: const EdgeInsets.fromLTRB(12, 22, 10, 15),
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[
Colors.transparent,
Colors.black87,
],
tileMode: TileMode.mirror,
),
borderRadius: floor == 1
? null
: const BorderRadius.all(Radius.circular(6))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
children: [
Text(
item.modules.moduleDynamic.major.ugcSeason
.durationText,
style: TextStyle(
fontSize: Theme.of(context)
.textTheme
.labelMedium!
.fontSize,
color: Colors.white),
),
const SizedBox(width: 10),
Text(
item.modules.moduleDynamic.major.ugcSeason
.stat.play,
style: TextStyle(
fontSize: Theme.of(context)
.textTheme
.labelMedium!
.fontSize,
color: Colors.white),
),
const SizedBox(width: 10),
Text(
item.modules.moduleDynamic.major.ugcSeason
.stat.danmaku,
style: TextStyle(
fontSize: Theme.of(context)
.textTheme
.labelMedium!
.fontSize,
color: Colors.white),
)
],
),
Image.asset(
'assets/images/play.png',
width: 70,
height: 70,
),
],
),
)),
],
);
}),
),
const SizedBox(height: 6),
Padding(
padding: floor == 1
? const EdgeInsets.only(left: 12, right: 12)
: EdgeInsets.zero,
child: Text(
item.modules.moduleDynamic.major.ugcSeason.title,
maxLines: 1,
style: const TextStyle(fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(height: 4),
],
);
default:
return const Text('渲染出错了');
}
@ -269,4 +378,57 @@ class DynamicPanel extends StatelessWidget {
],
);
}
Widget picWidget(item, context) {
List pictures = item.modules.moduleDynamic.major.draw.items;
int len = pictures.length;
List picList = [];
List<Widget> list = [];
for (var i = 0; i < len; i++) {
picList.add(pictures[i].src);
list.add(
LayoutBuilder(
builder: (context, BoxConstraints box) {
return GestureDetector(
onTap: () {
Get.toNamed('/preview',
arguments: {'initialPage': i, 'imgList': picList});
},
child: NetworkImgLayer(
src: pictures[i].src,
width: box.maxWidth,
height: box.maxWidth,
),
);
},
),
);
}
return LayoutBuilder(
builder: (context, BoxConstraints box) {
double maxWidth = box.maxWidth;
double crossCount = len < 3 ? 2 : 3;
double height = maxWidth /
crossCount *
(len % crossCount == 0
? len ~/ crossCount
: len ~/ crossCount + 1) +
6;
return Container(
padding: const EdgeInsets.only(top: 6),
height: height,
child: GridView.count(
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: crossCount.toInt(),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
childAspectRatio: 1,
children: list,
),
);
},
);
}
}