我有一個由 2 x N 網格專案組成的LazyVGrid內部 a NavigationView。每個專案都包含一些不同長度的文本,我希望它們與最大專案的高度相同。
這是我的代碼的一個版本,可以復制并粘貼到 SwiftUI Playground 中:
import SwiftUI
import PlaygroundSupport
struct TileGridView: View {
private var items: [GridItem] {
Array(
repeating: GridItem(
.adaptive(minimum: 150),
spacing: 10
),
count: 2
)
}
var body: some View {
NavigationView {
LazyVGrid(columns: items, spacing: 10) {
TileCellView(
text: "Lorem Ipsum"
)
TileCellView(
text: "Lorem Ipsum Dolem"
)
TileCellView(
text: "Lorem ipsum dolor sit amet"
)
TileCellView(
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
)
TileCellView(
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor"
)
}
.padding(.horizontal)
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Image(systemName: "checkmark")
}
ToolbarItem(placement: .navigationBarTrailing) {
Image(systemName: "checkmark")
}
}
}.navigationViewStyle(.stack)
}
}
struct TileCellView: View {
@State private var isSelected: Bool = false
let text: String
var body: some View {
ZStack {
Text(text)
.padding()
.frame(maxWidth: .infinity)
.background(
RoundedRectangle(cornerRadius: 25, style: .continuous)
.foregroundColor(.blue)
)
.contentShape(Rectangle())
.onTapGesture {
isSelected = true
}
NavigationLink(
isActive: $isSelected,
destination: {
Text("hi")
},
label: {
EmptyView()
}
).hidden()
}
}
}
PlaygroundPage.current.setLiveView(TileGridView())
現在我嘗試添加一個PreferenceKeytoTileGridView來找到最大專案的框架高度,但我無法讓它作業。
更新:這是我的代碼,其中包含一個首選項鍵:
struct TileGridView: View {
@State private var priceHeight: CGFloat?
private var items: [GridItem] {
Array(
repeating: GridItem(
.adaptive(minimum: 150),
spacing: 10
),
count: 2
)
}
var body: some View {
NavigationView {
LazyVGrid(columns: items, spacing: 10) {
Group {
TileCellView(
text: "Lorem Ipsum",
height: $priceHeight
)
TileCellView(
text: "Lorem Ipsum Dolem",
height: $priceHeight
)
TileCellView(
text: "Lorem ipsum dolor sit amet",
height: $priceHeight
)
TileCellView(
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
height: $priceHeight
)
TileCellView(
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor",
height: $priceHeight
)
}
.background(
GeometryReader { geometry in
Color.clear.preference(
key: HeightPreferenceKey.self,
value: geometry.size.height
)
}
)
}
.onPreferenceChange(HeightPreferenceKey.self) {
priceHeight = $0
}
.padding(.horizontal)
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Image(systemName: "checkmark")
}
ToolbarItem(placement: .navigationBarTrailing) {
Image(systemName: "checkmark")
}
}
}.navigationViewStyle(.stack)
}
}
private extension TileGridView {
struct HeightPreferenceKey: PreferenceKey {
static let defaultValue: CGFloat = 0
static func reduce(
value: inout CGFloat,
nextValue: () -> CGFloat
) {
value = max(value, nextValue())
}
}
}
struct TileCellView: View {
@State private var isSelected: Bool = false
let text: String
@Binding var height: CGFloat?
var body: some View {
ZStack {
Text(text)
.padding()
.frame(maxWidth: .infinity)
.frame(height: height)
.background(
RoundedRectangle(cornerRadius: 25, style: .continuous)
.foregroundColor(.blue)
)
.contentShape(Rectangle())
.onTapGesture {
isSelected = true
}
NavigationLink(
isActive: $isSelected,
destination: {
Text("hi")
},
label: {
EmptyView()
}
).hidden()
}
}
}
有誰知道如何使這項作業?謝謝!
uj5u.com熱心網友回復:
您遇到的問題是雙重的:1. 您正在讀取整個LazyVGrid.的大小,而不是單個單元格的大小,2 PreferenceKey.在使用. PreferenceKey它的作用是讀取框架包含之前單元格想要的高度。然后取其中最大的一個,并將框架高度設定為該高度,我們使它們的大小都相同,并且剛好足以包含文本。我必須做的最后一件事是將藍色背景移出單元格,因為它必須在.frame(). LazyVGrid' or 為了清晰和簡潔,我還洗掉了與PreferenceKey`無關的那部分代碼。您的擴展名保持不變。所以,你得到這個:
struct TileGridView: View {
@State private var priceHeight: CGFloat = 50
private var items: [GridItem] {
Array(
repeating: GridItem(
.adaptive(minimum: 150),
spacing: 10
),
count: 2
)
}
var body: some View {
NavigationView {
LazyVGrid(columns: items, spacing: 10) {
Group {
TileCellView(text: "Lorem Ipsum")
.background(
GeometryReader { geometry in
Color.clear.preference(
key: HeightPreferenceKey.self,
value: geometry.size.height
)
}
)
.frame(height: priceHeight)
.background(
RoundedRectangle(cornerRadius: 25, style: .continuous)
.foregroundColor(.blue)
)
TileCellView(text: "Lorem Ipsum Dolem")
.background(
GeometryReader { geometry in
Color.clear.preference(
key: HeightPreferenceKey.self,
value: geometry.size.height
)
}
)
.frame(height: priceHeight)
.background(
RoundedRectangle(cornerRadius: 25, style: .continuous)
.foregroundColor(.blue)
)
TileCellView(text: "Lorem ipsum dolor sit amet")
.background(
GeometryReader { geometry in
Color.clear.preference(
key: HeightPreferenceKey.self,
value: geometry.size.height
)
}
)
.frame(height: priceHeight)
.background(
RoundedRectangle(cornerRadius: 25, style: .continuous)
.foregroundColor(.blue)
)
TileCellView(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit,")
.background(
GeometryReader { geometry in
Color.clear.preference(
key: HeightPreferenceKey.self,
value: geometry.size.height
)
}
)
.frame(height: priceHeight)
.background(
RoundedRectangle(cornerRadius: 25, style: .continuous)
.foregroundColor(.blue)
)
TileCellView(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor")
.background(
GeometryReader { geometry in
Color.clear.preference(
key: HeightPreferenceKey.self,
value: geometry.size.height
)
}
)
.background(
RoundedRectangle(cornerRadius: 25, style: .continuous)
.foregroundColor(.blue)
)
}
}
.onPreferenceChange(HeightPreferenceKey.self) {
priceHeight = $0
}
.padding(.horizontal)
}.navigationViewStyle(.stack)
}
}
struct TileCellView: View {
let text: String
var body: some View {
ZStack {
Text(text)
.padding()
.frame(maxWidth: .infinity)
.contentShape(Rectangle())
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/401738.html
