Я использую прокрутку для своих topCardView и BottomView. Когда я пытаюсь прокручивать каждый раз, выдается ошибка о недопустимых размерах кадра или иногда он зависает. Привязанное предпочтение SizePreferenceKey пыталось обновиться несколько раз за кадр.
Как я могу это исправить? Любую помощь я очень ценю.
Мой завершенный код:
import SwiftUI
struct ContentView: View {
var body: some View {
ScrollView(.vertical, showsIndicators: false, content: {
GeometryReader { reader in
topCardView
.offset(y: -reader.frame(in: .global).minY)
.frame(width: reader.size.width, height: reader.frame(in: .global).minY + 450)
}
.frame(height: 450)
VStack(spacing: 40) {
BottomView
}
.padding(.vertical, 32)
.padding(.horizontal, 16)
.background(
Color(red: 232/255, green: 230/255, blue: 225/255)
.cornerRadius(40)
)
.offset(y: -25)
})
}
@ViewBuilder
private var topCardView: some View {
ScrollView(.horizontal, showsIndicators: false) {
LazyHGrid(rows: Array(repeating: GridItem(), count: 1), spacing: 20) {
ForEach(0..<2) { _ in
RoundedRectangle(cornerRadius: 12)
.fill(Color(red: 248/255, green: 250/255, blue: 220/255))
.frame(width: 300, height: 377)
}
}
.padding(.horizontal, 20)
}
}
@ViewBuilder
private var BottomView: some View {
ForEach(0..<2) { _ in
VStack(alignment: .center) {
Text("Fastest Near You")
.bold()
.frame(width: UIScreen.main.bounds.width - 32 * 6, height: 35)
Text("Order your food here")
.frame(width: UIScreen.main.bounds.width - 32 * 4, height: 25)
LazyVGrid(columns: Array(repeating: GridItem(), count: 2), spacing: 12) {
ForEach(0..<4) { _ in
RoundedRectangle(cornerRadius: 12)
.fill(Color(red: 248/255, green: 250/255, blue: 220/255))
.frame(width: UIScreen.main.bounds.width / 2 - 24, height: 200)
}
}
.padding(.top, 20)
}
}
}
}
Изображение ошибки:

@BenzyNeez Иногда прокрутка все еще зависает. Я использовал динамическую высоту, поэтому, когда я прокручиваю вверх, topCardView поднимается вверх, это своего рода эффект параллакса.
@BenzyNeez, есть ли другой способ слегка переместить topCardView вверх при прокрутке вверх?





Я в комментариях спрашивал, зачем вы вообще задаете динамическую высоту кадра. Вы ответили, что хотите создать эффект параллакса.
Я думаю, этого можно добиться без использования динамической высоты кадра:
GeometryReader).frame(in: .scrollView) для ссылки на координатное пространство ScrollViewScrollViewVStack, который содержит их оба.zIndex к виду снизу, просто чтобы быть уверенным, что он всегда отображается над видом сверху.GeometryReader можно использовать для измерения размера экрана вместо UIScreen.main (который устарел).Так что, возможно, попробуйте что-то вроде этого:
struct ContentView: View {
var body: some View {
GeometryReader { outer in
let screenSize = outer.size
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 40) {
GeometryReader { reader in
let minY = reader.frame(in: .scrollView).minY
topCardView
.frame(maxHeight: .infinity)
.offset(y: -minY / 2)
}
.frame(height: screenSize.height / 2)
VStack(spacing: 40) {
bottomView(screenSize: screenSize)
}
.padding(.horizontal, 16)
.padding(.bottom, 40)
.background(
RoundedRectangle(cornerRadius: 40)
.fill(Color(red: 232/255, green: 230/255, blue: 225/255))
)
.zIndex(1)
}
}
}
}
@ViewBuilder
private var topCardView: some View {
// content as before
}
@ViewBuilder
private func bottomView(screenSize: CGSize) -> some View {
// content as before, but using screenSize instead of UIScreen.main.bounds
}
}

Большое спасибо. Идеально. И последнее, если мне нужно добавить интервал сверху, потому что у меня есть панель навигации, которая скрывает некоторую часть topView. Что бы вы порекомендовали мне, где я размещаю прокладку?
@IOSTech Рад слышать, что это помогло, спасибо, что приняли ответ. Чтобы освободить место для панели навигации, вы можете попробовать применить верхнее дополнение к ScrollView. Это разорвет контакт с вставкой безопасной области вверху, поэтому она больше не будет прокручиваться за верхнюю часть экрана. Но, предположительно, ваша панель навигации все равно покрывает эту область? Альтернативно, вы можете применить отступ к самому topCardView.
Я попробовал ваш код, и сообщение об ошибке появляется только после значительной прокрутки вверх. Вероятно, это потому, что
minY + 450имеет отрицательное значение. Вы можете это исправить, изменив его наheight: max(1, reader.frame(in: .global).minY + 450). Но мне интересно, зачем вам вообще устанавливать динамическую высоту кадра?