调整滚动视图会出现偏移错误

问题描述 投票:0回答:1

我正在为我的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)
            }
        }
    }
}

错误图片:

Error Image

ios swiftui scrollview
1个回答
0
投票

我在评论中问,为什么你要设置动态框架高度。您回复说,您想要创建视差效果。

我认为这可以在不使用动态框架高度的情况下实现:

  • 顶部部分可以简单地使用其周围容器的整个高度(
    GeometryReader
  • 对于视差效果,可以将 y 偏移应用于顶部部分,该部分是滚动高度的一部分
  • 如果您运行的是 iOS 17 或更高版本,您可以使用
    .frame(in: .scrollView)
    来引用
    ScrollView
  • 的坐标空间
  • 对于早期的 iOS 版本,您可以将
    ScrollView
    的坐标空间命名为
  • 要管理两个部分之间的初始间距,请使用包含它们的
    VStack
  • 我建议将
    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
    }
}

Animation

© www.soinside.com 2019 - 2024. All rights reserved.