SwiftUI 子视图被剪辑在滚动视图中

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

我使用

ScrollView
LazyHStack
创建了一个轮播视图,如下所示:

struct CarouselView<Content: View>: View {
    let content: Content
    @State private var currentIndex = 0
    @State private var contentSize: CGSize = .zero
    
    private let showsIndicators: Bool
    private let spacing: CGFloat
    private let shouldSnap: Bool
    
    init(showsIndicators: Bool = true,
         spacing: CGFloat = .zero,
         shouldSnap: Bool = false,
         @ViewBuilder content: @escaping () -> Content) {
        self.content = content()
        self.showsIndicators = showsIndicators
        self.spacing = spacing
        self.shouldSnap = shouldSnap
    }
    
    var body: some View {
        VStack {
            ScrollView(.horizontal, showsIndicators: showsIndicators) {
                LazyHStack(spacing: spacing) {
                    content
                }.apply {
                    if #available(iOS 17.0, *), shouldSnap {
                        $0.scrollTargetLayout()
                    } else {
                        $0
                    }
                }
            }
            .clipped() // tried to add this to avoid clipping
            .apply {
                if #available(iOS 17.0, *), shouldSnap {
                    $0.scrollTargetBehavior(.viewAligned)
                } else {
                    $0
                }
            }
        }
    }
}

extension View {
    func apply<V: View>(@ViewBuilder _ block: (Self) -> V) -> V { block(self) }
}

然后我按如下方式使用它:

struct ContentView: View {
    let imagesNames = ["img-1", "img-2", "img-3", "img-4"]
    let numberOfLines = [2, 1, 3, 2]
    
    var body: some View {
        
        VStack(spacing: 40) {
            continuousCarousel
        }
        
    }
    
    private var continuousCarousel: some View {
        CarouselView(showsIndicators: true,
                     spacing: 20) {
            ForEach(0 ..< imagesNames.count, id: \.self) { index in
                createImageTile(with: imagesNames[index],
                                height: 70,
                                numberOfLines: numberOfLines[index])
            }
        }
    }
    
    private func createImageTile(with image: String,
                                 height: CGFloat,
                                 numberOfLines: Int) -> some View {
        VStack(spacing: .zero) {
            Image(image)
                .resizable()
                .cornerRadius(30)
                .scaledToFit()
                .aspectRatio(contentMode: .fill)
                .frame(width: 200, height: 100)
                .padding(.bottom, 30)
            
            Text("Headline")
                .bold()
                .padding(.bottom, 10)
            
            ForEach(0 ..< numberOfLines, id: \.self) { _ in
                Text("Some description here")
                    .padding(.bottom, 5)
            }
            
            Spacer() // added to top align content
        }
    }
}

这给了我大部分想要的结果,但是,正如你所看到的,图像的顶部被安全区域剪掉了:

enter image description here

我尝试按照此

answer
的建议将clipped修饰符添加到滚动视图,但无济于事。

我该如何解决这个问题?

ios swift swiftui hstack
1个回答
0
投票

我认为你只需要更改函数中应用于

Image
的修饰符
createImageTile
:

  • 您正在设置
    .aspectRatio(contentMode: .fill)
    。这会覆盖之前的修饰符
    .scaledToFit()
    ,因此是多余的。
  • 要修复顶部剪裁,请尝试在设置框架尺寸后应用圆角线。
  • 修饰符
  • .cornerRadius
     已弃用,建议使用 
    .clipShape
     代替。
顺便说一句,传递给此函数的

height

 参数并未被使用。

这是使用缩放填充的更新版本。然后使用圆角矩形将图像剪切到包含帧 (200x100)。

Image(image) .resizable() // .cornerRadius(30) // .scaledToFit() // .aspectRatio(contentMode: .fill) .scaledToFill() .frame(width: 200, height: 100) .clipShape(RoundedRectangle(cornerRadius: 30)) .padding(.bottom, 30)
    
© www.soinside.com 2019 - 2024. All rights reserved.