|
|
@@ -40,16 +40,18 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
|
|
|
_titleCard(),
|
|
|
Flexible(
|
|
|
child: Obx(() {
|
|
|
- return ListView(
|
|
|
+ return ListView.builder(
|
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
|
|
- children: [
|
|
|
- ...controller.photoGroups.map((group) => Column(
|
|
|
- children: [
|
|
|
- _buildPhotoGroup(group: group),
|
|
|
- SizedBox(height: 15.h),
|
|
|
- ],
|
|
|
- ))
|
|
|
- ],
|
|
|
+ itemCount: controller.photoGroups.length,
|
|
|
+ itemBuilder: (context, index) {
|
|
|
+ final group = controller.photoGroups[index];
|
|
|
+ return Column(
|
|
|
+ children: [
|
|
|
+ _buildPhotoGroup(group: group),
|
|
|
+ SizedBox(height: 15.h),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ },
|
|
|
);
|
|
|
}),
|
|
|
),
|
|
|
@@ -225,13 +227,14 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
|
|
|
),
|
|
|
SizedBox(
|
|
|
height: 148.h,
|
|
|
- child: ListView(
|
|
|
+ child: ListView.builder(
|
|
|
scrollDirection: Axis.horizontal,
|
|
|
- physics: BouncingScrollPhysics(),
|
|
|
- children: [
|
|
|
+ physics: const BouncingScrollPhysics(),
|
|
|
+ itemCount: ((group.images.length - 1) / 4).ceil() + 1, // 1 为大图组
|
|
|
+ itemBuilder: (context, index) {
|
|
|
// 第一张大图
|
|
|
- if (group.images.isNotEmpty)
|
|
|
- GestureDetector(
|
|
|
+ if (index == 0 && group.images.isNotEmpty) {
|
|
|
+ return GestureDetector(
|
|
|
onTap: () => controller.clickImage(
|
|
|
group.images, 0, PhotosType.similarPhotos),
|
|
|
child: SizedBox(
|
|
|
@@ -242,47 +245,43 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
|
|
|
children: [
|
|
|
Container(
|
|
|
decoration: ShapeDecoration(
|
|
|
- color: Colors.white.withValues(alpha: 0.12),
|
|
|
+ color: Colors.white.withAlpha(30),
|
|
|
shape: RoundedRectangleBorder(
|
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
|
),
|
|
|
),
|
|
|
child: ClipRRect(
|
|
|
- borderRadius: BorderRadius.circular(8.r),
|
|
|
- child: AssetEntityImage(
|
|
|
- width: 148.w,
|
|
|
- height: 148.h,
|
|
|
- group.images[0],
|
|
|
- fit: BoxFit.cover,
|
|
|
- thumbnailSize:
|
|
|
- const ThumbnailSize.square(300),
|
|
|
- isOriginal: false,
|
|
|
- frameBuilder: Styles.customFrameBuilder(
|
|
|
- width: 120.w,
|
|
|
- height: 120.w,
|
|
|
- ),
|
|
|
- )),
|
|
|
+ borderRadius: BorderRadius.circular(8.r),
|
|
|
+ child: AssetEntityImage(
|
|
|
+ group.images[0],
|
|
|
+ width: 148.w,
|
|
|
+ height: 148.h,
|
|
|
+ fit: BoxFit.cover,
|
|
|
+ thumbnailSize: const ThumbnailSize.square(300),
|
|
|
+ isOriginal: false,
|
|
|
+ frameBuilder: Styles.customFrameBuilder(
|
|
|
+ width: 120.w,
|
|
|
+ height: 120.w,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
),
|
|
|
+ // Best result 标签
|
|
|
Positioned(
|
|
|
left: 8.w,
|
|
|
top: 8.h,
|
|
|
child: Container(
|
|
|
width: 108.w,
|
|
|
height: 26.h,
|
|
|
- padding: EdgeInsets.symmetric(
|
|
|
- horizontal: 8.w,
|
|
|
- vertical: 4.h,
|
|
|
- ),
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
|
|
|
decoration: ShapeDecoration(
|
|
|
- color: Colors.black.withValues(alpha: 0.74),
|
|
|
+ color: Colors.black.withAlpha(190),
|
|
|
shape: RoundedRectangleBorder(
|
|
|
- borderRadius:
|
|
|
- BorderRadius.circular(14.21.r),
|
|
|
+ borderRadius: BorderRadius.circular(14.21.r),
|
|
|
),
|
|
|
),
|
|
|
child: Row(
|
|
|
- mainAxisAlignment:
|
|
|
- MainAxisAlignment.spaceAround,
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
|
children: [
|
|
|
Assets.images.iconSimilarBest.image(
|
|
|
width: 11.37.w,
|
|
|
@@ -290,7 +289,6 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
|
|
|
),
|
|
|
Text(
|
|
|
'Best result',
|
|
|
- textAlign: TextAlign.center,
|
|
|
style: TextStyle(
|
|
|
color: Colors.white,
|
|
|
fontSize: 13.sp,
|
|
|
@@ -301,127 +299,108 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
+ // 选中状态
|
|
|
Positioned(
|
|
|
right: 4.w,
|
|
|
bottom: 4.h,
|
|
|
child: GestureDetector(
|
|
|
- onTap: () => controller.toggleImageSelection(
|
|
|
- group.images, 0),
|
|
|
- child: Container(
|
|
|
- child: group.isImageSelected(group.images[0])
|
|
|
- ? Center(
|
|
|
- child:
|
|
|
- Assets.images.iconSelected.image(
|
|
|
- width: 20.w,
|
|
|
- height: 20.h,
|
|
|
- ),
|
|
|
- )
|
|
|
- : Center(
|
|
|
- child: Assets.images.iconUnselected
|
|
|
- .image(
|
|
|
- width: 20.w,
|
|
|
- height: 20.h,
|
|
|
- ),
|
|
|
- ),
|
|
|
- ),
|
|
|
+ onTap: () =>
|
|
|
+ controller.toggleImageSelection(group.images, 0),
|
|
|
+ child: Obx(() {
|
|
|
+ return group.isImageSelected(group.images[0])
|
|
|
+ ? Assets.images.iconSelected.image(
|
|
|
+ width: 20.w,
|
|
|
+ height: 20.h,
|
|
|
+ )
|
|
|
+ : Assets.images.iconUnselected.image(
|
|
|
+ width: 20.w,
|
|
|
+ height: 20.h,
|
|
|
+ );
|
|
|
+ }),
|
|
|
),
|
|
|
),
|
|
|
],
|
|
|
);
|
|
|
}),
|
|
|
),
|
|
|
- ),
|
|
|
- // 其他图片2x2网格
|
|
|
- if (group.images.length > 1)
|
|
|
- ...List.generate(((group.images.length - 1) / 4).ceil(),
|
|
|
- (gridIndex) {
|
|
|
- return Container(
|
|
|
- margin: EdgeInsets.only(left: 8.w),
|
|
|
- width: 142.w,
|
|
|
- child: GridView.count(
|
|
|
- physics: NeverScrollableScrollPhysics(),
|
|
|
- crossAxisCount: 2,
|
|
|
- mainAxisSpacing: 8.h,
|
|
|
- crossAxisSpacing: 8.w,
|
|
|
- children: List.generate(
|
|
|
- min(4, group.images.length - 1 - gridIndex * 4),
|
|
|
- (index) {
|
|
|
- final realIndex = gridIndex * 4 + index + 1;
|
|
|
- return GestureDetector(
|
|
|
- onTap: () => controller.clickImage(group.images,
|
|
|
- realIndex, PhotosType.similarPhotos),
|
|
|
- child: Obx(() {
|
|
|
- return Container(
|
|
|
- decoration: ShapeDecoration(
|
|
|
- color: Colors.white.withValues(alpha: 0.12),
|
|
|
- shape: RoundedRectangleBorder(
|
|
|
- borderRadius: BorderRadius.circular(8.r),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 剩余小图网格(从 index = 1 开始)
|
|
|
+ final gridIndex = index - 1;
|
|
|
+ final start = 1 + gridIndex * 4;
|
|
|
+ final end = min(start + 4, group.images.length);
|
|
|
+ final subImages = group.images.sublist(start, end);
|
|
|
+
|
|
|
+ return Container(
|
|
|
+ margin: EdgeInsets.only(left: 8.w),
|
|
|
+ width: 142.w,
|
|
|
+ child: GridView.builder(
|
|
|
+ itemCount: subImages.length,
|
|
|
+ physics: const NeverScrollableScrollPhysics(),
|
|
|
+ gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
|
|
+ crossAxisCount: 2,
|
|
|
+ mainAxisSpacing: 8.h,
|
|
|
+ crossAxisSpacing: 8.w,
|
|
|
+ ),
|
|
|
+ itemBuilder: (context, i) {
|
|
|
+ final realIndex = start + i;
|
|
|
+ final image = group.images[realIndex];
|
|
|
+ return GestureDetector(
|
|
|
+ onTap: () => controller.clickImage(
|
|
|
+ group.images, realIndex, PhotosType.similarPhotos),
|
|
|
+ child: Obx(() {
|
|
|
+ final isSelected = group.isImageSelected(image);
|
|
|
+ return Stack(
|
|
|
+ children: [
|
|
|
+ Container(
|
|
|
+ decoration: ShapeDecoration(
|
|
|
+ color: Colors.white.withAlpha(30),
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
+ borderRadius: BorderRadius.circular(8.r),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ child: ClipRRect(
|
|
|
+ borderRadius: BorderRadius.circular(8.r),
|
|
|
+ child: AssetEntityImage(
|
|
|
+ image,
|
|
|
+ width: 142.w,
|
|
|
+ fit: BoxFit.cover,
|
|
|
+ isOriginal: false,
|
|
|
+ thumbnailSize: const ThumbnailSize.square(300),
|
|
|
+ frameBuilder: Styles.customFrameBuilder(
|
|
|
+ width: 120.w,
|
|
|
+ height: 120.w,
|
|
|
),
|
|
|
),
|
|
|
- child: Stack(
|
|
|
- children: [
|
|
|
- ClipRRect(
|
|
|
- borderRadius:
|
|
|
- BorderRadius.circular(8.r),
|
|
|
- child: AssetEntityImage(
|
|
|
- group.images[realIndex],
|
|
|
- width: 142.w,
|
|
|
- frameBuilder:
|
|
|
- Styles.customFrameBuilder(
|
|
|
- width: 120.w,
|
|
|
- height: 120.w,
|
|
|
- ),
|
|
|
- thumbnailSize:
|
|
|
- const ThumbnailSize.square(300),
|
|
|
- isOriginal: false,
|
|
|
- fit: BoxFit.cover,
|
|
|
- ),
|
|
|
- ),
|
|
|
- Positioned(
|
|
|
- right: 4.w,
|
|
|
- bottom: 4.h,
|
|
|
- child: Obx(() {
|
|
|
- final isSelected =
|
|
|
- group.isImageSelected(
|
|
|
- group.images[realIndex]);
|
|
|
- return GestureDetector(
|
|
|
- onTap: () =>
|
|
|
- controller.toggleImageSelection(
|
|
|
- group.images, realIndex),
|
|
|
- child: Container(
|
|
|
- child: isSelected
|
|
|
- ? Center(
|
|
|
- child: Assets
|
|
|
- .images.iconSelected
|
|
|
- .image(
|
|
|
- width: 20.w,
|
|
|
- height: 20.h,
|
|
|
- ),
|
|
|
- )
|
|
|
- : Center(
|
|
|
- child: Assets
|
|
|
- .images.iconUnselected
|
|
|
- .image(
|
|
|
- width: 20.w,
|
|
|
- height: 20.h,
|
|
|
- ),
|
|
|
- ),
|
|
|
- ),
|
|
|
- );
|
|
|
- }),
|
|
|
- ),
|
|
|
- ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Positioned(
|
|
|
+ right: 4.w,
|
|
|
+ bottom: 4.h,
|
|
|
+ child: GestureDetector(
|
|
|
+ onTap: () => controller.toggleImageSelection(
|
|
|
+ group.images, realIndex),
|
|
|
+ child: isSelected
|
|
|
+ ? Assets.images.iconSelected.image(
|
|
|
+ width: 20.w,
|
|
|
+ height: 20.h,
|
|
|
+ )
|
|
|
+ : Assets.images.iconUnselected.image(
|
|
|
+ width: 20.w,
|
|
|
+ height: 20.h,
|
|
|
),
|
|
|
- );
|
|
|
- }),
|
|
|
- );
|
|
|
- },
|
|
|
- ),
|
|
|
- ),
|
|
|
- );
|
|
|
- }),
|
|
|
- ],
|
|
|
- ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }),
|
|
|
+ );
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ },
|
|
|
+ )
|
|
|
),
|
|
|
GestureDetector(
|
|
|
onTap: () => controller.clickSingleGroupDelete(group.images),
|