Во-первых, я новичок в Swiftui.
Мне нужна сетка просмотра, в которой размер каждого элемента изменяется в зависимости от количества элементов в сетке, и мне нужно расширять каждый элемент сетки при нажатии.
В конце концов мне удалось разложить элементы по мере необходимости (см. Рис. 1) и расширить их.
Unfortunately I am not able to properly bring the expanded item in front of all other views (see Fig 2 and Fig 3) using zIndex.
Рис 3
Я также попытался встроить VStack и HStack в ZStack, но ничего не изменилось.
Как я могу поместить расширенный элемент наверх?
Под моим кодом .
struct ContentViewNew: View {
private let columns: Int = 6
private let rows: Int = 4
@ObservedObject var viewModel: ViewModel
var cancellables = Set<AnyCancellable>()
init() {
viewModel = ViewModel(rows: rows, columns: columns)
viewModel.objectWillChange.sink { _ in
print("viewModel Changed")
}.store(in: &cancellables)
}
var body: some View {
GeometryReader { geometryProxy in
let hSpacing: CGFloat = 7
let vSpacing: CGFloat = 7
let hSize = (geometryProxy.size.width - hSpacing * CGFloat(columns + 1)) / CGFloat(columns)
let vSize = (geometryProxy.size.height - vSpacing * CGFloat(rows + 1)) / CGFloat(rows)
let size = min(hSize, vSize)
VStack {
ForEach(0 ..< viewModel.rows, id: \.self) { row in
Spacer()
HStack {
Spacer()
ForEach(0 ..< viewModel.columns, id: \.self) { column in
GeometryReader { widgetProxy in
ItemWiew(info: viewModel.getItem(row: row, column: column), size: size, zoomedSize: 0.80 * geometryProxy.size.width)
.offset(x: viewModel.getItem(row: row, column: column).zoomed ? (geometryProxy.size.width / 2.0 - (widgetProxy.frame(in: .global).origin.x + widgetProxy.size.width / 2.0)) : 0,
y: viewModel.getItem(row: row, column: column).zoomed ? geometryProxy.size.height / 2.0 - (widgetProxy.frame(in: .global).origin.y + widgetProxy.size.height / 2.0) : 0)
.onTapGesture {
viewModel.zoom(row: row, column: column)
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.zIndex(viewModel.getItem(row: row, column: column).zoomed ? 10000 : 0)
.background(Color.gray)
}
Spacer()
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.background(Color.blue)
Spacer()
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.background(Color.yellow)
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.background(Color.green)
}
}
struct ItemWiew: View {
@ObservedObject var info: ItemInfo
var size: CGFloat
init(info: ItemInfo, size: CGFloat, zoomedSize: CGFloat) {
self.info = info
self.size = size
if self.info.size == 0 {
self.info.size = size
self.info.zoomedSize = zoomedSize
}
}
var body: some View {
VStack {
Print("Drawing Widget with size \(self.info.size)")
Image(systemName: info.symbol)
.font(.system(size: 30))
.frame(width: info.size, height: info.size)
.background(info.color)
.cornerRadius(10)
}
}
}
class ItemInfo: ObservableObject, Identifiable {
var symbol: String
var color: Color
var zoomed = false
@Published var size: CGFloat
@Published var originalSize: CGFloat
@Published var zoomedSize: CGFloat
init(symbol: String, color: Color) {
self.symbol = symbol
self.color = color
size = 0.0
originalSize = 0.0
zoomedSize = 0.0
}
func toggleZoom() {
if zoomed {
size = originalSize
color = .red
} else {
size = zoomedSize
color = .white
}
zoomed.toggle()
}
}
class ViewModel: ObservableObject {
private var symbols = ["keyboard", "hifispeaker.fill", "printer.fill", "tv.fill", "desktopcomputer", "headphones", "tv.music.note", "mic", "plus.bubble", "video"]
private var colors: [Color] = [.yellow, .purple, .green]
@Published var listData = [ItemInfo]()
var rows = 0
var columns = 0
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
for _ in 0 ..< rows {
for j in 0 ..< columns {
listData.append(ItemInfo(symbol: symbols[j % symbols.count], color: colors[j % colors.count]))
}
}
}
func getItem(row: Int, column: Int) -> ItemInfo {
return listData[columns * row + column]
}
func zoom(row: Int, column: Int) {
listData[columns * row + column].toggleZoom()
objectWillChange.send()
}
}