【问题标题】:Placing a rectangle in front of ScrollView affects scrolling在 ScrollView 前面放置一个矩形会影响滚动
【发布时间】:2021-01-06 11:22:31
【问题描述】:

我需要在 ScrollView 前面放置一个半透明矩形,但是当我将所有内容(矩形和 ScrollView)都放在 ZStack 内时,滚动和触摸事件在此矩形内停止工作。

Atm 我正在使用 .background 修饰符,因为它不影响滚动,但我仍在寻找使其工作的方法正确地将矩形放置在我的 ScrollView 上方(前面)

有什么办法可以将 View 放在 ScrollView 上,这样就不会影响它的功能?

这是我现在使用的代码(我更改了颜色并移除了不透明度以使对象可见,因为我的原始矩形是半透明的并且包含几乎不可见的渐变)

struct ContentView: View {
    
    var body: some View {
        ZStack {
            
            ScrollView {
                LazyVStack(spacing: 0) {
                    ForEach(0...100, id:\.self) { val in
                        ZStack {
                            Text("test")
                                .font(.system(size: 128))
                        } // ZStack
                        .background(Color.blue)
                    } // ForEach
                }
            }
            .background(RadialGradient(gradient: Gradient(stops: [
                                                            .init(color: Color.blue, location: 0),
                                                            .init(color: Color.red, location: 1)]), center: .top, startRadius: 1, endRadius: 200)
                            .mask(
                                VStack(spacing: 0) {
                                    Rectangle()
                                        .frame(width: 347, height: 139)
                                        .padding(.top, 0)
                                    Spacer()
                                }
                            ))
            
        }
    }
}

【问题讨论】:

    标签: swiftui swiftui-scrollview


    【解决方案1】:

    这是一种可能的开始方法 - 使用 UIVisualEffectView。而Blur 视图取自How do I pass a View into a struct while getting its height also? 主题。

    struct ScrollContentView: View {
        
        var body: some View {
            ZStack {
                
                ScrollView {
                    LazyVStack(spacing: 0) {
                        ForEach(0...100, id:\.self) { val in
                            ZStack {
                                Text("test")
                                    .font(.system(size: 128))
                            } // ZStack
                            .background(Color.blue)
                        } // ForEach
                    }
                }
                Blur(style:  .systemThinMaterialLight)
                    .mask(
                        VStack(spacing: 0) {
                            Rectangle()
                                .frame(width: 347, height: 139)
                                .padding(.top, 0)
                            Spacer()
                        }
                    )
                    .allowsHitTesting(false)
            }
        }
    }
    

    【讨论】:

    • 谢谢! ;) 我在下面发布了更新的代码。它运作良好;)
    【解决方案2】:

    我决定在这里发布一个解决方案。它基于 Asperi 建议的方法。

    2Asperi:谢谢,我一如既往地感谢您的帮助。

    我尝试了将 .opacity & mask 应用到 Blur,但没有奏效。

    所以我在 makeUIView 中的 .layer 属性上应用了遮罩,效果很好

    import SwiftUI
    
    struct ContentView: View {
        
        var body: some View {
            ZStack {
                ZStack {
                ScrollView {
                    LazyVStack(spacing: 0) {
                        ForEach(0...100, id:\.self) { val in
                            ZStack {
                                Text("test")
                                    .font(.system(size: 128))
                            } // ZStack
                            .background(Color.white)
                        } // ForEach
                    }
                }
                    Blur(style: .systemThinMaterial)
                                    .mask(
                                        VStack(spacing: 0) {
                                            Rectangle()
                                                .frame(width: 347, height: 139)
                                                .padding(.top, 0)
                                            Spacer()
                                        }
                                    )
                        .allowsHitTesting(false)
                }
            }
        }
    }
    
    struct Blur: UIViewRepresentable {
        var style: UIBlurEffect.Style = .systemMaterial
        func makeUIView(context: Context) -> UIVisualEffectView {
            
            let blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: style))
            
            let gradientMaskLayer = CAGradientLayer()
            
            gradientMaskLayer.type = .radial
            
            gradientMaskLayer.frame = CGRect(x: 0, y: 0, width: 347, height: 256)
            
            gradientMaskLayer.colors = [UIColor.black.cgColor, UIColor.clear.cgColor]
            
            gradientMaskLayer.startPoint = CGPoint(x: 0.5, y: 0)
            gradientMaskLayer.endPoint = CGPoint(x: 1, y: 1)
            
            gradientMaskLayer.locations = [0 , 0.6]
            blurEffectView.layer.mask = gradientMaskLayer
            
            return blurEffectView
        }
        func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
            uiView.effect = UIBlurEffect(style: style)
        }
    }
    

    我唯一不明白的是为什么 startPoint 和 endPoint 仅在我将它们设置为 [0.5,0] 和 [1,1] 而不是 [0.5,0] 和 [0.5,1] 时才起作用 - 我预计它应该确定径向渐变的方向,在我的情况下,它应该从 .topCenter 到 .topBottom (确实如此,但我不了解 endPoint 的性质)..

    【讨论】:

      猜你喜欢
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-23
      • 2018-02-22
      • 1970-01-01
      • 2017-12-01
      • 1970-01-01
      相关资源
      最近更新 更多