
- 在ImagePreviewPager中引入ImagePreviewSource枚举,支持本地和远程图片的统一处理。 - 优化OptimizedDynamicCardView,新增图片预览状态管理,集成全屏图片预览功能。 - 更新OptimizedImageGrid以支持图片点击事件,触发预览弹窗,提升用户体验。
87 lines
3.2 KiB
Swift
87 lines
3.2 KiB
Swift
import SwiftUI
|
|
|
|
enum ImagePreviewSource: Identifiable, Equatable {
|
|
case local(UIImage)
|
|
case remote(String)
|
|
var id: String {
|
|
switch self {
|
|
case .local(let img):
|
|
return String(describing: img.hashValue)
|
|
case .remote(let url):
|
|
return url
|
|
}
|
|
}
|
|
static func == (lhs: ImagePreviewSource, rhs: ImagePreviewSource) -> Bool {
|
|
switch (lhs, rhs) {
|
|
case let (.local(l), .local(r)):
|
|
return l.pngData() == r.pngData()
|
|
case let (.remote(l), .remote(r)):
|
|
return l == r
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
struct ImagePreviewPager: View {
|
|
let images: [ImagePreviewSource]
|
|
@Binding var currentIndex: Int
|
|
let onClose: () -> Void
|
|
|
|
// 本地图片构造器
|
|
init(images: [UIImage], currentIndex: Binding<Int>, onClose: @escaping () -> Void) {
|
|
self.images = images.map { .local($0) }
|
|
self._currentIndex = currentIndex
|
|
self.onClose = onClose
|
|
}
|
|
// 远程图片构造器
|
|
init(images: [String], currentIndex: Binding<Int>, onClose: @escaping () -> Void) {
|
|
self.images = images.map { .remote($0) }
|
|
self._currentIndex = currentIndex
|
|
self.onClose = onClose
|
|
}
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .topTrailing) {
|
|
Color.black.ignoresSafeArea()
|
|
TabView(selection: $currentIndex) {
|
|
ForEach(Array(images.enumerated()), id: \ .element.id) { idx, source in
|
|
Group {
|
|
switch source {
|
|
case .local(let img):
|
|
Image(uiImage: img)
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fit)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.background(Color.black)
|
|
case .remote(let urlStr):
|
|
CachedAsyncImage(url: urlStr) { image in
|
|
image
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fit)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.background(Color.black)
|
|
} placeholder: {
|
|
Rectangle()
|
|
.fill(Color.gray.opacity(0.3))
|
|
.overlay(
|
|
ProgressView()
|
|
.progressViewStyle(CircularProgressViewStyle(tint: .white.opacity(0.6)))
|
|
.scaleEffect(0.8)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
.tag(idx)
|
|
}
|
|
}
|
|
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
|
|
Button(action: { onClose() }) {
|
|
Image(systemName: "xmark.circle.fill")
|
|
.font(.system(size: 32))
|
|
.foregroundColor(.white)
|
|
.padding(24)
|
|
}
|
|
}
|
|
}
|
|
} |