Wallpaper-Genie/lib/page/wallpaper_detail_v2/wallpaper_detail_v2_view.dart
xuhang-x 3bf5f4fa10 1
2024-07-26 18:41:05 +08:00

402 lines
14 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flip_card/flip_card.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:gradient_borders/box_borders/gradient_box_border.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
import 'package:wallpaperx/common/components/view_state_widget.dart';
import 'package:wallpaperx/entity/image_model.dart';
import 'package:wallpaperx/generated/assets.dart';
import 'wallpaper_detail_v2_controller.dart';
class WallpaperDetailV2View extends GetView<WallpaperDetailV2Controller> {
const WallpaperDetailV2View({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
extendBodyBehindAppBar: true,
extendBody: true,
body: FlipCard(
flipOnTouch: false,
controller: controller.flipCardController,
fill: Fill.fillBack,
side: CardSide.FRONT,
direction: FlipDirection.HORIZONTAL,
front: Stack(
fit: StackFit.expand,
children: [
_buildPhotoView(),
_buildBottomOption(context),
],
),
back: _buildImageInfo(context),
),
);
}
/// 图片PageView
Widget _buildPhotoView() {
return Obx(() {
if (controller.wallpaperList.isEmpty) {
return Container();
}
return PhotoViewGallery.builder(
itemCount: controller.wallpaperList.length,
scrollPhysics: const BouncingScrollPhysics(),
wantKeepAlive: true,
gaplessPlayback: true,
builder: (context, index) {
return PhotoViewGalleryPageOptions.customChild(
child: PhotoView(
enableRotation: true,
imageProvider: CachedNetworkImageProvider(
controller.wallpaperList[index].imageUrl,
),
initialScale: PhotoViewComputedScale.contained,
minScale: PhotoViewComputedScale.contained * 0.5,
maxScale: PhotoViewComputedScale.covered * 3,
loadingBuilder: (context, event) => loadingView(),
errorBuilder: (BuildContext context, Object error,
StackTrace? stackTrace) =>
errorView,
),
);
},
pageController: controller.pageController,
onPageChanged: (index) => controller.onPageChanged(index),
);
});
}
/// 底部选项
Widget _buildBottomOption(context) {
return Positioned(
bottom: 0,
left: 0,
right: 0,
child: Column(
children: [
ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom),
width: double.infinity,
height: 70.h,
decoration: const BoxDecoration(
color: Color.fromRGBO(0, 0, 0, 0.65),
),
clipBehavior: Clip.hardEdge,
child: Row(
children: [
16.horizontalSpace,
_buildOptionItem(
Assets.iconBackBig,
'',
Get.back,
),
Expanded(child: Container()),
Obx(() => _buildOptionItem(
controller.isFavorite.value
? Assets.iconFavorite
: Assets.iconUnFavorite,
'',
controller.collectionImage,
)),
24.horizontalSpace,
_buildOptionItem(
Assets.iconDownload,
'',
controller.downloadImg,
),
24.horizontalSpace,
_buildOptionItem(
Assets.iconImgInfo,
'',
controller.flipCardAndShowAd,
),
16.horizontalSpace,
],
),
),
),
),
],
),
);
}
/// 图片详情
Widget _buildImageInfo(context) {
return GetBuilder<WallpaperDetailV2Controller>(
id: 'buildImageInfo',
builder: (logic) {
ImageModel model = controller.wallpaperList[controller.position];
return Container(
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12).r,
image: DecorationImage(
fit: BoxFit.cover,
image: CachedNetworkImageProvider(
controller.wallpaperList[controller.position].imageUrl,
),
),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: const Color(0xff000000).withOpacity(.8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
63.verticalSpace,
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
clipBehavior: Clip.none,
children: [
Image.asset(
Assets.iconImgDelTip,
color: Colors.white,
width: 52.w,
height: 52.w,
),
Positioned(
left: -15.w,
top: 15.w,
child: Image.asset(
Assets.iconStarSymbolS,
width: 20.w,
),
),
Positioned(
left: -8.w,
top: 10.w,
child: Image.asset(
Assets.iconStarSymbolM,
width: 20.w,
),
),
Positioned(
right: -12.w,
bottom: -2.w,
child: Image.asset(
Assets.iconStarSymbolL,
width: 25.w,
),
),
],
),
],
),
37.verticalSpace,
Expanded(
child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 30).w,
children: [
Wrap(
spacing: 8.w,
runSpacing: 8.w,
children: model.tags!
.map((e) => tagItem(e.taglabel))
.toList(),
),
32.verticalSpace,
genInfo(
Image.asset(
Assets.iconSampler,
color: Colors.white,
width: 28.w,
),
"Sampler",
model.generateInfo!.samplingMethod ?? "",
),
23.verticalSpace,
genInfo(
Image.asset(
Assets.iconCfgScale,
color: Colors.white,
width: 28.w,
),
"CFG scale",
model.generateInfo!.cfgScale.toString(),
),
23.verticalSpace,
genInfo(
Image.asset(
Assets.iconSteps,
color: Colors.white,
width: 28.w,
),
"Steps",
model.generateInfo!.samplingStep.toString(),
),
23.verticalSpace,
genInfo(
Image.asset(
Assets.iconSeed,
color: Colors.white,
width: 28.w,
),
"Seed",
model.generateInfo!.seed.toString(),
),
20.verticalSpace,
Text(
"Prompt",
textAlign: TextAlign.start,
style:
TextStyle(color: Colors.white, fontSize: 16.sp),
),
12.verticalSpace,
Text(
model.generateInfo?.prompt ?? "",
textAlign: TextAlign.start,
style: TextStyle(
color: const Color(0xffA1A9B3), fontSize: 14.sp),
),
20.verticalSpace,
Text(
"Negative Prompt",
textAlign: TextAlign.start,
style:
TextStyle(color: Colors.white, fontSize: 16.sp),
),
12.verticalSpace,
Text(
model.generateInfo?.negativePrompt ?? "",
textAlign: TextAlign.start,
style: TextStyle(
color: const Color(0xffA1A9B3), fontSize: 14.sp),
),
],
),
),
24.verticalSpace,
Container(
height: 70.h,
width: double.infinity,
padding: EdgeInsets.only(
left: 16,
right: 16,
bottom: MediaQuery.of(context).padding.bottom,
).w,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildOptionItem(
Assets.iconBackBig,
'',
Get.back,
),
GestureDetector(
onTap: () =>
controller.copyPrompt(model.generateInfo),
child: Container(
width: 200.w,
height: 40.h,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white.withOpacity(.2),
borderRadius: BorderRadius.circular(50).r,
),
child: Text(
"Copy Prompt",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white, fontSize: 14.sp),
),
),
),
_buildOptionItem(
Assets.iconImgInfo,
'',
controller.flipCard,
),
],
),
),
],
),
),
),
);
},
);
}
Widget genInfo(icon, title, content) {
return Row(
children: [
icon,
16.horizontalSpace,
SizedBox(
width: 250.w,
child: Text(
title + content,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.start,
style: TextStyle(color: Colors.white, fontSize: 16.sp),
),
),
],
);
}
Widget tagItem(tag) {
return GestureDetector(
onTap: () => controller.toCategoryItem(tag),
child: Container(
decoration: BoxDecoration(
border: const GradientBoxBorder(
gradient: LinearGradient(colors: [
Color(0xffBEEF32),
Color(0xff2795E5),
Color(0xff8041FD),
]),
width: 1,
),
borderRadius: BorderRadius.circular(50.r),
),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12).w,
child: Text(
"#$tag",
style: TextStyle(color: Colors.white, fontSize: 14.sp),
),
),
),
);
}
Widget _buildOptionItem(String iconName, String option, Function() onTap) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
child: Image.asset(
iconName,
width: 24.w,
height: 24.w,
color: Colors.white,
),
),
);
}
}