修复相机历史导入页网格缩略图重叠与溢出问题。
采用 1:1 方形容器约束单元格布局,并统一网格间距与边距常量。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -0,0 +1,11 @@
|
||||
import SwiftUI
|
||||
|
||||
/// 相机历史导入页布局常量。
|
||||
enum CameraHistoryImportDesign {
|
||||
static let gridColumns = 3
|
||||
static let gridHorizontalSpacing: CGFloat = 2
|
||||
static let gridVerticalSpacing: CGFloat = 2
|
||||
static let contentHorizontalPadding: CGFloat = 12
|
||||
static let sectionSpacing: CGFloat = 12
|
||||
static let thumbnailCornerRadius: CGFloat = 4
|
||||
}
|
||||
@ -11,51 +11,61 @@ struct CameraHistoryImportPhotoCell: View {
|
||||
@State private var thumbnail: UIImage?
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
Group {
|
||||
if let thumbnail {
|
||||
Image(uiImage: thumbnail)
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
} else {
|
||||
Color.gray.opacity(0.15)
|
||||
.overlay {
|
||||
ProgressView()
|
||||
.scaleEffect(0.7)
|
||||
}
|
||||
Color.clear
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.overlay {
|
||||
thumbnailContent
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
.clipShape(RoundedRectangle(cornerRadius: CameraHistoryImportDesign.thumbnailCornerRadius))
|
||||
.overlay(alignment: .topTrailing) {
|
||||
statusBadge
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
guard !isImported else { return }
|
||||
onToggle()
|
||||
}
|
||||
.task(id: photo.id) {
|
||||
guard thumbnail == nil else { return }
|
||||
if let data = await thumbnailProvider(), let image = UIImage(data: data) {
|
||||
thumbnail = image
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.clipped()
|
||||
}
|
||||
|
||||
if isImported {
|
||||
Text("已导入")
|
||||
.font(.system(size: 10, weight: .medium))
|
||||
.foregroundStyle(.white)
|
||||
.padding(.horizontal, 6)
|
||||
.padding(.vertical, 3)
|
||||
.background(Color.black.opacity(0.55))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||
.padding(6)
|
||||
} else {
|
||||
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
|
||||
.font(.system(size: 22))
|
||||
.foregroundStyle(isSelected ? AppDesign.primary : .white)
|
||||
.shadow(radius: 2)
|
||||
.padding(6)
|
||||
}
|
||||
@ViewBuilder
|
||||
private var thumbnailContent: some View {
|
||||
if let thumbnail {
|
||||
Image(uiImage: thumbnail)
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
} else {
|
||||
Color.gray.opacity(0.15)
|
||||
.overlay {
|
||||
ProgressView()
|
||||
.scaleEffect(0.7)
|
||||
}
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
guard !isImported else { return }
|
||||
onToggle()
|
||||
}
|
||||
.task(id: photo.id) {
|
||||
guard thumbnail == nil else { return }
|
||||
if let data = await thumbnailProvider(), let image = UIImage(data: data) {
|
||||
thumbnail = image
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var statusBadge: some View {
|
||||
if isImported {
|
||||
Text("已导入")
|
||||
.font(.system(size: 10, weight: .medium))
|
||||
.foregroundStyle(.white)
|
||||
.padding(.horizontal, 6)
|
||||
.padding(.vertical, 3)
|
||||
.background(Color.black.opacity(0.55))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||
.padding(6)
|
||||
} else {
|
||||
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
|
||||
.font(.system(size: 22))
|
||||
.foregroundStyle(isSelected ? AppDesign.primary : .white)
|
||||
.shadow(color: .black.opacity(0.35), radius: 2, x: 0, y: 1)
|
||||
.padding(6)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,8 +21,9 @@ struct CameraHistoryImportSectionHeader: View {
|
||||
.foregroundStyle(AppDesign.primary)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.horizontal, CameraHistoryImportDesign.contentHorizontalPadding)
|
||||
.padding(.vertical, 8)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(WiredTransferDesign.pageBackground)
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,10 +70,10 @@ struct CameraHistoryImportView: View {
|
||||
|
||||
private func photoList(sections: [CameraPhotoSection]) -> some View {
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 12, pinnedViews: [.sectionHeaders]) {
|
||||
LazyVStack(spacing: CameraHistoryImportDesign.sectionSpacing, pinnedViews: [.sectionHeaders]) {
|
||||
ForEach(sections) { section in
|
||||
Section {
|
||||
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: 2) {
|
||||
LazyVGrid(columns: gridColumns, spacing: CameraHistoryImportDesign.gridVerticalSpacing) {
|
||||
ForEach(section.photos, id: \.id) { photo in
|
||||
CameraHistoryImportPhotoCell(
|
||||
photo: photo,
|
||||
@ -94,10 +94,18 @@ struct CameraHistoryImportView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 2)
|
||||
.padding(.horizontal, CameraHistoryImportDesign.contentHorizontalPadding)
|
||||
.padding(.bottom, 16)
|
||||
}
|
||||
}
|
||||
|
||||
private var gridColumns: [GridItem] {
|
||||
Array(
|
||||
repeating: GridItem(.flexible(), spacing: CameraHistoryImportDesign.gridHorizontalSpacing),
|
||||
count: CameraHistoryImportDesign.gridColumns
|
||||
)
|
||||
}
|
||||
|
||||
private func emptyView(message: String) -> some View {
|
||||
VStack(spacing: 16) {
|
||||
Text(message)
|
||||
|
||||
Reference in New Issue
Block a user