import 'dart:convert';
|
import 'dart:io';
|
|
import 'package:flutter/material.dart';
|
import '../../model/video/home_type_model.dart';
|
import '../../model/video/video_model.dart';
|
import '../../ui/video/video_detail.dart';
|
import '../../utils/jump_page.dart';
|
import '../../utils/pageutils.dart';
|
import '../../utils/ui_constant.dart';
|
import '../../utils/ui_utils.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
import '../../utils/video/video_util.dart';
|
|
import '../../main.dart';
|
|
class VideoListUIUtil {
|
static Widget getHomeTypeItem(
|
double width, HomeTypeModel homeType, BuildContext context) {
|
double padding = 8;
|
width = width - padding * 2;
|
Widget videoList = Container();
|
|
List<Widget> list =
|
List.filled(homeType.homeVideoList!.length, Container());
|
//填充大图
|
for (var i = 0; i < homeType.homeVideoList!.length; i++) {
|
HomeVideoModel homeVideo = homeType.homeVideoList![i];
|
if (homeVideo.bigPicture!) {
|
list[i] = getVideoItemColumn_1(width, homeVideo, context, native: Platform.isIOS);
|
} else {
|
switch (homeType.columns) {
|
case 1:
|
list[i] =
|
getVideoItemColumn_1(width, homeVideo, context, native: Platform.isIOS);
|
break;
|
case 2:
|
list[i] =
|
getVideoItemColumn_2(width, homeVideo, context, native: Platform.isIOS);
|
break;
|
case 3:
|
list[i] =
|
getVideoItemColumn_3(width, homeVideo, context, native: Platform.isIOS);
|
break;
|
default:
|
list[i] =
|
getVideoItemColumn_2(width, homeVideo, context, native: Platform.isIOS);
|
}
|
}
|
}
|
|
if (homeType.columns! <= 3) {
|
videoList = Wrap(
|
alignment: WrapAlignment.spaceBetween,
|
runSpacing: 10,
|
spacing: 7,
|
children: list,
|
);
|
} else {
|
videoList = ListView.separated(
|
shrinkWrap: true,
|
scrollDirection: Axis.horizontal,
|
itemBuilder: (BuildContext context, int index) {
|
return getVideoItemColumn_n(
|
width, homeType.homeVideoList![index], context);
|
},
|
itemCount: homeType.homeVideoList!.length,
|
separatorBuilder: (BuildContext context, int index) {
|
return Container(
|
width: 10,
|
);
|
},
|
);
|
}
|
|
return Container(
|
padding: const EdgeInsets.all(8),
|
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Container(
|
padding: const EdgeInsets.only(top: 0, bottom: 10),
|
child: Row(children: [
|
Text(
|
homeType.name!,
|
style:
|
const TextStyle(color: Color(0xFF5F5F5F), fontSize: 16),
|
)
|
])),
|
videoList,
|
],
|
),
|
);
|
}
|
|
static Widget getVideoItemColumn_1(
|
double mx, HomeVideoModel homeVideo, BuildContext context,
|
{bool native = false}) {
|
return InkWell(
|
onTap: () {
|
jumpVideoDetail(context, homeVideo.video, native);
|
},
|
child: Stack(
|
alignment: Alignment.bottomLeft,
|
children: [
|
ClipRRect(
|
borderRadius: BorderRadius.circular(12.5),
|
child: VideoImage(
|
(homeVideo.picture != null && homeVideo.picture!.isNotEmpty)
|
? homeVideo.picture!
|
: ((homeVideo.video!.hpicture != null &&
|
homeVideo.video!.hpicture!.isNotEmpty)
|
? homeVideo.video!.hpicture
|
: homeVideo.video!.picture),
|
width: mx,
|
height: mx * 0.4382,
|
),
|
),
|
Container(
|
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
|
decoration: const BoxDecoration(
|
borderRadius: BorderRadius.only(
|
bottomLeft: Radius.circular(12.5),
|
bottomRight: Radius.circular(12.5)),
|
gradient: LinearGradient(
|
begin: Alignment.topCenter,
|
end: Alignment.bottomCenter,
|
colors: [
|
Color(0x00000000),
|
Color(0x80000000),
|
],
|
),
|
),
|
child: Row(
|
children: [
|
Text(
|
homeVideo.video!.tag!,
|
style: _getTagStyle(),
|
),
|
Expanded(
|
child: Container(),
|
),
|
_getScoreText("9")
|
],
|
),
|
)
|
],
|
));
|
}
|
|
static Widget getVideoItemColumn_2(
|
double mx, HomeVideoModel homeVideo, BuildContext context,
|
{bool native = false}) {
|
return InkWell(
|
onTap: () {
|
jumpVideoDetail(context, homeVideo.video, native);
|
},
|
child: Container(
|
width: (mx - 7.5) / 2,
|
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Stack(
|
alignment: Alignment.bottomLeft,
|
children: [
|
ClipRRect(
|
borderRadius: BorderRadius.circular(12.5),
|
child: VideoImage(
|
(homeVideo.picture != null &&
|
homeVideo.picture!.isNotEmpty)
|
? homeVideo.picture!
|
: ((homeVideo.video!.hpicture != null &&
|
homeVideo.video!.hpicture!.isNotEmpty)
|
? homeVideo.video!.hpicture
|
: homeVideo.video!.picture),
|
width: (mx - 7.5) / 2,
|
height: ((mx - 7.5) / 2) * 0.5629,
|
fit: BoxFit.cover,
|
),
|
),
|
Container(
|
padding: EdgeInsets.fromLTRB(5, 5, 5, 5),
|
decoration: const BoxDecoration(
|
borderRadius: BorderRadius.only(
|
bottomLeft: Radius.circular(12.5),
|
bottomRight: Radius.circular(12.5)),
|
gradient: LinearGradient(
|
begin: Alignment.topCenter,
|
end: Alignment.bottomCenter,
|
colors: [
|
Color(0x00000000),
|
Color(0x80000000),
|
],
|
),
|
),
|
child: Row(
|
children: [
|
Text(
|
homeVideo.video!.tag != null
|
? homeVideo.video!.tag!
|
: "",
|
style: _getTagStyle()),
|
Expanded(
|
child: Container(),
|
),
|
_getScoreText("9.3")
|
],
|
),
|
)
|
],
|
),
|
Text(
|
homeVideo.video!.name!,
|
maxLines: 2,
|
overflow: TextOverflow.ellipsis,
|
style: _getTitleStyle(),
|
),
|
],
|
),
|
));
|
}
|
|
static Widget getVideoItemColumn_3(
|
double mx, HomeVideoModel homeVideo, BuildContext context,
|
{bool native = false}) {
|
return InkWell(
|
onTap: () {
|
jumpVideoDetail(context, homeVideo.video, native);
|
},
|
child: Container(
|
width: (mx - 8 * 2) / 3,
|
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Stack(
|
alignment: Alignment.bottomLeft,
|
children: [
|
ClipRRect(
|
borderRadius: BorderRadius.circular(12.5),
|
child: VideoImage(
|
(homeVideo.picture != null &&
|
homeVideo.picture!.isNotEmpty)
|
? homeVideo.picture!
|
: ((homeVideo.video!.vpicture != null &&
|
homeVideo.video!.vpicture!.isNotEmpty)
|
? homeVideo.video!.vpicture
|
: homeVideo.video!.picture),
|
width: (mx - 8) / 3,
|
height: ((mx - 8) / 3) * 1.4,
|
),
|
),
|
Container(
|
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
|
decoration: const BoxDecoration(
|
borderRadius: BorderRadius.only(
|
bottomLeft: Radius.circular(12.5),
|
bottomRight: Radius.circular(12.5)),
|
gradient: LinearGradient(
|
begin: Alignment.topCenter,
|
end: Alignment.bottomCenter,
|
colors: [
|
Color(0x00000000),
|
Color(0x80000000),
|
],
|
),
|
),
|
child: Row(
|
children: [
|
Expanded(
|
child: Text(homeVideo.video!.tag!,
|
maxLines: 1,
|
overflow: TextOverflow.ellipsis,
|
style: _getTagStyle()),
|
),
|
_getScoreText(homeVideo.video!.score)
|
],
|
),
|
)
|
],
|
),
|
Text(
|
homeVideo.video!.name!,
|
maxLines: 2,
|
overflow: TextOverflow.ellipsis,
|
style: _getTitleStyle(),
|
)
|
],
|
),
|
));
|
}
|
|
static Widget getVideoItemColumn_n(
|
double mx, HomeVideoModel homeVideo, BuildContext context,
|
{bool native = false}) {
|
return InkWell(
|
onTap: () {
|
jumpVideoDetail(context, homeVideo.video, native);
|
},
|
child: Container(
|
width: (mx - 7.5) / 2.5,
|
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Stack(
|
alignment: Alignment.bottomLeft,
|
children: [
|
ClipRRect(
|
borderRadius: BorderRadius.circular(12.5),
|
child: VideoImage(
|
(homeVideo.picture != null &&
|
homeVideo.picture!.isNotEmpty)
|
? homeVideo.picture!
|
: ((homeVideo.video!.hpicture != null &&
|
homeVideo.video!.hpicture!.isNotEmpty)
|
? homeVideo.video!.hpicture
|
: homeVideo.video!.picture),
|
width: (mx - 7.5) / 2.5,
|
height: ((mx - 7.5) / 2.5) * 0.5629,
|
),
|
),
|
Container(
|
padding: EdgeInsets.fromLTRB(5, 5, 5, 5),
|
decoration: const BoxDecoration(
|
borderRadius: BorderRadius.only(
|
bottomLeft: Radius.circular(12.5),
|
bottomRight: Radius.circular(12.5)),
|
gradient: LinearGradient(
|
begin: Alignment.topCenter,
|
end: Alignment.bottomCenter,
|
colors: [
|
Color(0x00000000),
|
Color(0x80000000),
|
],
|
),
|
),
|
child: Row(
|
children: [
|
Text(homeVideo.video!.tag!, style: _getTagStyle()),
|
Expanded(
|
child: Container(),
|
),
|
_getScoreText(homeVideo.video!.score)
|
],
|
),
|
)
|
],
|
),
|
Text(
|
homeVideo.video!.name!,
|
maxLines: 2,
|
overflow: TextOverflow.ellipsis,
|
style: _getTitleStyle(),
|
),
|
],
|
),
|
));
|
}
|
|
static Widget getSearchVideoAlbum(
|
BuildContext context, VideoInfoModel videoInfo) {
|
const double paddingLeft = 10;
|
const double paddingRight = 10;
|
double episodeWidth = (MediaQuery.of(context).size.width -
|
paddingRight -
|
paddingLeft -
|
10 * 4 -
|
1) /
|
5;
|
|
double episodeHeight = episodeWidth * 0.656;
|
|
return Container(
|
alignment: Alignment.topLeft,
|
padding: const EdgeInsets.fromLTRB(
|
paddingLeft,
|
0,
|
paddingRight,
|
15,
|
),
|
child: Column(
|
children: [
|
SizedBox(
|
height: 154,
|
child: Row(
|
children: [
|
//封面
|
ClipRRect(
|
borderRadius: BorderRadius.circular(6),
|
child: VideoImage(
|
videoInfo.vpicture != null &&
|
videoInfo.vpicture!.isNotEmpty
|
? videoInfo.vpicture
|
: videoInfo.picture,
|
width: 112,
|
height: 154),
|
),
|
Container(
|
width: 14,
|
),
|
Expanded(
|
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Row(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Expanded(
|
child: Text(
|
videoInfo.name!,
|
maxLines: 2,
|
overflow: TextOverflow.ellipsis,
|
style: const TextStyle(
|
color: Color(0xFF232323), fontSize: 16),
|
)),
|
Container(
|
width: 10,
|
),
|
_getAlbumScoreText(videoInfo.score)
|
]),
|
Container(
|
height: 8,
|
),
|
Text(
|
videoInfo.tag!,
|
maxLines: 1,
|
overflow: TextOverflow.ellipsis,
|
style: const TextStyle(
|
color: Color(0xFFAEAEAE), fontSize: 12),
|
),
|
Container(
|
height: 10,
|
),
|
Text(
|
videoInfo.mainActor ?? "",
|
maxLines: 2,
|
overflow: TextOverflow.ellipsis,
|
style: const TextStyle(
|
color: Color(0xFFAEAEAE), fontSize: 12),
|
),
|
Expanded(child: Container()),
|
Container(
|
alignment: Alignment.centerRight,
|
child: InkWell(
|
onTap: () {
|
jumpVideoDetail(context, videoInfo, false);
|
},
|
child: Container(
|
width: 127,
|
height: 30,
|
alignment: Alignment.center,
|
decoration: BoxDecoration(
|
borderRadius: BorderRadius.circular(8),
|
color: ColorConstant.theme),
|
child: const Text(
|
"立即观看",
|
style: TextStyle(
|
color: Colors.white, fontSize: 14),
|
),
|
)))
|
],
|
))
|
],
|
)),
|
//剧集
|
videoInfo.videoDetailList!.isNotEmpty
|
? Container(
|
alignment: Alignment.centerLeft,
|
margin: const EdgeInsets.only(top: 16),
|
child: Wrap(
|
alignment: WrapAlignment.start,
|
spacing: 10,
|
children: videoInfo.videoDetailList!
|
.map((e) => getTVEpisodeItem(
|
e.tag, episodeWidth, episodeHeight, context,
|
onClick: () {
|
jumpVideoDetail(context, videoInfo, false,
|
position: int.tryParse(e.tag!) != null
|
? int.parse(e.tag!)
|
: 0);
|
}))
|
.toList()))
|
: Container()
|
],
|
),
|
);
|
}
|
|
static Widget getSearchVideoCommon(
|
BuildContext context, VideoInfoModel videoInfo) {
|
const double paddingLeft = 10;
|
const double paddingRight = 10;
|
return InkWell(
|
onTap: () {
|
jumpVideoDetail(context, videoInfo, false);
|
},
|
child: Container(
|
alignment: Alignment.topLeft,
|
padding: const EdgeInsets.fromLTRB(paddingLeft, 20, paddingRight, 0),
|
child: Column(
|
children: [
|
SizedBox(
|
height: 76,
|
child: Row(
|
children: [
|
//封面
|
ClipRRect(
|
borderRadius: BorderRadius.circular(6),
|
child: VideoImage(
|
videoInfo.picture,
|
width: 136,
|
),
|
),
|
Container(
|
width: 14,
|
),
|
Expanded(
|
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Text(
|
videoInfo.name!,
|
maxLines: 2,
|
overflow: TextOverflow.ellipsis,
|
style: TextStyle(
|
color: Color(0xFF232323), fontSize: 16),
|
),
|
Expanded(child: Container()),
|
Container(
|
alignment: Alignment.centerRight,
|
child: Text(
|
videoInfo.duration ?? "",
|
maxLines: 1,
|
overflow: TextOverflow.ellipsis,
|
style: const TextStyle(
|
color: Color(0xFFB8AFB5), fontSize: 12),
|
))
|
],
|
))
|
],
|
)),
|
],
|
),
|
));
|
}
|
|
static Widget getRecommendVideo(
|
BuildContext context, VideoInfoModel videoInfo) {
|
return Container(
|
alignment: Alignment.topLeft,
|
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
child: Column(
|
children: [
|
Container(
|
height: 76,
|
child: Row(
|
children: [
|
//封面
|
ClipRRect(
|
borderRadius: BorderRadius.circular(6),
|
child: VideoImage(
|
VideoUtil.getHPicture(videoInfo),
|
width: 136,
|
),
|
),
|
Container(
|
width: 14,
|
),
|
Expanded(
|
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Row(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Expanded(
|
child: Text(
|
videoInfo.name!,
|
maxLines: 1,
|
overflow: TextOverflow.ellipsis,
|
style: const TextStyle(
|
color: Color(0xFF232323), fontSize: 16),
|
)),
|
Container(
|
width: 10,
|
),
|
_getAlbumScoreText(videoInfo.score)
|
]),
|
Text(
|
videoInfo.tag ?? "",
|
maxLines: 1,
|
overflow: TextOverflow.ellipsis,
|
style: const TextStyle(
|
color: Color(0xFFAEAEAE), fontSize: 12),
|
),
|
Expanded(child: Container()),
|
const Text(
|
"",
|
maxLines: 2,
|
overflow: TextOverflow.ellipsis,
|
style:
|
TextStyle(color: Color(0xFFAEAEAE), fontSize: 12),
|
),
|
],
|
))
|
],
|
)),
|
],
|
),
|
);
|
}
|
|
static TextStyle _getTagStyle() {
|
return TextStyle(color: Colors.white, fontSize: 12);
|
}
|
|
static TextStyle _getTitleStyle() {
|
return TextStyle(color: Color(0xFF464646), fontSize: 14);
|
}
|
|
static TextStyle _getSubTitleStyle() {
|
return TextStyle(color: Color(0xFFB3ADB3), fontSize: 12);
|
}
|
|
static Text _getScoreText(String? score) {
|
if (score == null || score.isEmpty) {
|
return const Text("");
|
}
|
List<TextSpan> spanList = [];
|
spanList.add(TextSpan(
|
text: score.split(".")[0],
|
style: const TextStyle(fontSize: 13, color: Color(0xFFFB9F00))));
|
if (score.split(".").length > 1) {
|
spanList.add(TextSpan(
|
text: ".${score.split(".")[1]}",
|
style: const TextStyle(fontSize: 9, color: Color(0xFFFB9F00))));
|
}
|
spanList.add(const TextSpan(
|
text: "分", style: TextStyle(fontSize: 8, color: Color(0xAAFB9F00))));
|
return Text.rich(TextSpan(children: spanList));
|
}
|
|
static Text _getAlbumScoreText(String? score) {
|
if (score == null || score.isEmpty) {
|
return Text("");
|
}
|
List<TextSpan> spanList = [];
|
spanList.add(TextSpan(
|
text: score, style: TextStyle(fontSize: 15, color: Color(0xFFFF9C00))));
|
|
spanList.add(const TextSpan(
|
text: "分", style: TextStyle(fontSize: 12, color: Color(0xFFB8B8B8))));
|
return Text.rich(TextSpan(children: spanList));
|
}
|
|
static Widget getTVEpisodeItem(
|
text, double width, double height, BuildContext context,
|
{checked: false, VoidCallback? onClick}) {
|
return InkWell(
|
onTap: () {
|
if (onClick != null) {
|
onClick();
|
}
|
},
|
child: Container(
|
width: width,
|
alignment: Alignment.center,
|
height: height,
|
decoration: BoxDecoration(
|
color: checked ? ColorConstant.theme : Colors.white,
|
borderRadius: BorderRadius.circular(10),
|
border: Border.all(
|
width: checked ? 0 : DimenUtil.getOnePixel(context),
|
color: const Color(0xFFBBBBBB))),
|
child: Text(text,
|
style: TextStyle(
|
color: checked ? Colors.white : Color(0xFF232323),
|
fontSize: 16)),
|
));
|
}
|
|
static Widget getShowEpisodeItem(text, BuildContext context,
|
{checked: false, VoidCallback? onClick}) {
|
return InkWell(
|
onTap: () {
|
if (onClick != null) {
|
onClick();
|
}
|
},
|
child: Container(
|
padding: const EdgeInsets.all(10),
|
width: 200,
|
alignment: Alignment.topLeft,
|
decoration: BoxDecoration(
|
color: checked ? ColorConstant.theme : Colors.white,
|
borderRadius: BorderRadius.circular(10),
|
border: Border.all(
|
width: checked ? 0 : DimenUtil.getOnePixel(context),
|
color: const Color(0xFFBBBBBB))),
|
child: Text(text,
|
maxLines: 3,
|
overflow: TextOverflow.ellipsis,
|
style: TextStyle(
|
color: checked ? Colors.white : const Color(0xFF232323),
|
fontSize: 16)),
|
));
|
}
|
}
|
|
Widget VideoImage(url, {fit = BoxFit.cover, double? width, double? height}) {
|
return CachedNetworkImage(
|
imageUrl: url,
|
fit: fit,
|
width: width,
|
height: height,
|
placeholder: (context, st) => Container(
|
color: const Color(0xFFFFE8F0),
|
),
|
errorWidget: (context, url, error) => const Icon(Icons.error),
|
);
|
}
|
|
Widget CommonImage(String url,
|
{fit = BoxFit.cover,
|
double? width,
|
double? height,
|
Widget? defaultWidget}) {
|
if (url.startsWith("http")) {
|
return CachedNetworkImage(
|
imageUrl: url,
|
fit: fit,
|
width: width,
|
height: height,
|
placeholder: (context, st) =>
|
defaultWidget ??
|
Container(
|
color: const Color(0xFFFFE8F0),
|
),
|
errorWidget: (context, url, error) =>
|
defaultWidget ?? const Icon(Icons.error),
|
);
|
} else {
|
return Image.asset(
|
url,
|
width: width,
|
height: height,
|
fit: fit,
|
);
|
}
|
}
|
|
void jumpVideoDetail(BuildContext context, VideoInfoModel? video, bool native,
|
{int position = 0}) {
|
JumpPageUtil.jumpPage("VideoDetailPage", context,
|
params: {"position": position, "video": video!.toJson()}, native: native);
|
}
|