Files
e-party-iOS/yana/MVVM/View/NineGridImagePicker.swift
edwinQQQ 6b960f53b4 feat: 更新Splash视图及登录模型逻辑
- 将SplashV2替换为SplashPage,优化应用启动流程。
- 在LoginModels中将用户ID参数更改为加密后的ID,增强安全性。
- 更新AppConfig中的API基础URL,确保与生产环境一致。
- 在CommonComponents中添加底部Tab栏图标映射逻辑,提升用户体验。
- 新增NineGridImagePicker组件,支持多图选择功能,优化CreateFeedPage的图片选择逻辑。
- 移除冗余的BottomTabView组件,简化视图结构,提升代码整洁性。
- 在MainPage中整合创建动态页面的逻辑,优化导航体验。
- 新增MePage视图,提供用户信息管理功能,增强应用的可用性。
2025-09-26 10:53:00 +08:00

124 lines
5.4 KiB
Swift
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 SwiftUI
import PhotosUI
struct NineGridImagePicker: View {
@Binding var images: [UIImage]
var maxCount: Int = 9
var cornerRadius: CGFloat = 16
var spacing: CGFloat = 8
var horizontalPadding: CGFloat = 20
var onTapImage: (Int) -> Void = { _ in }
@State private var pickerItems: [PhotosPickerItem] = []
var body: some View {
GeometryReader { geometry in
let columns = Array(repeating: GridItem(.flexible(), spacing: spacing), count: 3)
let columnsCount: CGFloat = 3
let totalSpacing = spacing * (columnsCount - 1)
let availableWidth = geometry.size.width - horizontalPadding * 2
let cellSide = (availableWidth - totalSpacing) / columnsCount
LazyVGrid(columns: columns, spacing: spacing) {
ForEach(0..<maxCount, id: \.self) { index in
ZStack {
// DEBUG
#if DEBUG
if index >= images.count && !(index == images.count && images.count < maxCount) {
RoundedRectangle(cornerRadius: cornerRadius)
.fill(Color.white.opacity(0.08))
}
#endif
if index < images.count {
//
ZStack(alignment: .topTrailing) {
Image(uiImage: images[index])
.resizable()
.scaledToFill()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.contentShape(RoundedRectangle(cornerRadius: cornerRadius))
.onTapGesture { onTapImage(index) }
Button {
removeImage(at: index)
} label: {
Image(systemName: "xmark.circle.fill")
.foregroundColor(.white)
.background(Circle().fill(Color.black.opacity(0.4)))
.font(.system(size: 16, weight: .bold))
}
.padding(6)
.buttonStyle(.plain)
}
} else if index == images.count && images.count < maxCount {
//
PhotosPicker(
selection: $pickerItems,
maxSelectionCount: maxCount - images.count,
selectionBehavior: .ordered,
matching: .images
) {
ZStack {
RoundedRectangle(cornerRadius: cornerRadius)
.fill(Color(hex: 0x1C143A))
Image(systemName: "plus")
.foregroundColor(.white.opacity(0.6))
.font(.system(size: 32, weight: .semibold))
}
}
.onChange(of: pickerItems) { _, newItems in
handlePickerItems(newItems)
}
}
}
.frame(height: cellSide)
.clipShape(RoundedRectangle(cornerRadius: cornerRadius))
.contentShape(RoundedRectangle(cornerRadius: cornerRadius))
}
}
.padding(.horizontal, horizontalPadding)
}
.frame(height: gridHeight(forCount: max(images.count, 1)))
}
private func gridHeight(forCount count: Int) -> CGFloat {
//
// 3 = ceil(count / 3.0) GeometryReader
let screenWidth = UIScreen.main.bounds.width
let columnsCount: CGFloat = 3
let totalSpacing = spacing * (columnsCount - 1)
let availableWidth = screenWidth - horizontalPadding * 2
let side = (availableWidth - totalSpacing) / columnsCount
let rows = ceil(CGFloat(count) / 3.0)
let totalRowSpacing = spacing * max(rows - 1, 0)
return side * rows + totalRowSpacing
}
private func handlePickerItems(_ items: [PhotosPickerItem]) {
guard !items.isEmpty else { return }
Task { @MainActor in
var appended: [UIImage] = []
for item in items {
if images.count + appended.count >= maxCount { break }
if let data = try? await item.loadTransferable(type: Data.self),
let image = UIImage(data: data) {
appended.append(image)
}
}
if !appended.isEmpty {
images.append(contentsOf: appended)
}
pickerItems = []
}
}
private func removeImage(at index: Int) {
guard images.indices.contains(index) else { return }
images.remove(at: index)
}
}