如何防止按钮在 ScrollView 中被禁用

How do I prevent buttons being disabled inside a ScrollView

在下面的代码中,从一张卡片滑动到另一张卡片似乎禁用了 ScrollView 内的按钮。我已经将问题确定为 ScrollPart 中的 .mask 行(.clippedShape 产生了类似的问题并且不符合我的设计目标),但不幸的是,在我正在进行的实际项目中,我无法得到为了视觉效果去掉它

import SwiftUI

extension AnyTransition {
    public static func swipe(_ edge: Edge) -> AnyTransition {
        .asymmetric(insertion: move(edge: edge), removal: move(edge: edge.flip()))
    }
}

extension Edge {
    public func flip() -> Edge {
        switch self {
        case .bottom:
            return .top
        case .top:
            return .bottom
        case .leading:
            return .trailing
        case .trailing:
            return .leading
        }
    }
}

struct ContentView: View {
    @State var index: Int = 0
    @State var offset: CGFloat = 0
    @State var transition = AnyTransition.identity
    @State var ID = UUID()
    
    var body: some View {
        GeometryReader { geometry in
            ScrollPart(index: self.index)
                .frame(width: geometry.size.width)
                .background(Background())
                .offset(x: self.offset)
                .id(self.ID)
                .gesture(
                    DragGesture()
                        .onChanged {value in
                            self.offset = value.translation.width
                    }
                    .onEnded { _ in
                        if self.offset > geometry.size.width * 0.4 {
                            self.index += 1
                            self.ID = UUID()
                            
                            self.transition = .swipe(.leading)
                        }
                        if self.offset < -geometry.size.width * 0.4 {
                            self.index -= 1
                            self.ID = UUID()
                            
                            self.transition = .swipe(.trailing)
                        }
                        
                        self.offset = 0
                    }
                )
                .transition(self.transition)
                .animation(.easeOut)
        }
    }
}
import SwiftUI

struct ScrollPart: View {
    var index : Int
    @State var bool = false
    
    var body: some View {
        ScrollView {
            Spacer().frame(height: 300)
            Button (action: {self.bool.toggle()}){
                ZStack {
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(
                            style:
                            StrokeStyle(lineWidth: 1,
                                        dash: [10, 1])).foregroundColor(.white)
                        .frame(width: 120)
                        .foregroundColor(.green)
                Text("Index: \(self.index)")
                    .foregroundColor(.white)
                    .font(.title)
                .padding()
                }
            }
            Text(bool ? "True" : "False")
                .foregroundColor(.white)
                .font(.title)
        }
    .mask(Background())
    }
}
import SwiftUI

struct Background: View {
    var body: some View {
        GeometryReader { geometry in
            RoundedRectangle(cornerRadius: 10)
                .foregroundColor(.green)
                .frame(width: 0.9 * geometry.size.width, height: 0.9 * geometry.size.height)
        }
    }
}

我已经为此苦苦挣扎了一段时间,但我仍然希望有一些方法可以保留遮罩,同时解决 ScrollView 中按钮被禁用的问题。如果您滚动 ScrollView,该按钮会重新启用,但这仍然是一个设计缺陷,理想情况下可以修复。我对 UIKit 了解不多,我基本上才刚刚开始学习 SwiftUI,并且只在绝对必要时才学习旧方法,所以如果 UIKit 的回答记住我可能很难理解它,我将不胜感激 感谢您的帮助!

一种可能的解决方案是删除或修改 .mask(Background()), Apple Docs“The view which alpha the rendering system applies to the specified view.”中的掩码行。 “当你想将另一个视图的 alpha(不透明度)值应用到当前视图时,使用 mask(_:)。”应用具有相同背景的遮罩,在此背景视图内,几何 Reader 影响滚动视图内的按钮。

如果你评论 //.mask(Background) 对我来说很好用并且显示白色边框也很好。另一个使用掩码的解决方案在 ScrollView 上添加 VStack 并应用没有几何图形的掩码 Reader。如果你对这个蒙版应用不透明度也可以正常工作(将 .mask(Background1()) 更改为 .mask(Rectangle().opacity(0.6)))

    struct Background1: View {
      var body: some View {
         RoundedRectangle(cornerRadius: 10)
           .foregroundColor(.green)
         }
     }

    struct ScrollPart: View {
      var index : Int
      @State var bool = false

      var body: some View {
        ScrollView {
          VStack {
             Spacer().frame(height: 300)
             Button (action: {self.bool.toggle()}){
                ZStack {
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(
                            style:
                            StrokeStyle(lineWidth: 1, dash: [10,1])).foregroundColor(.white)
                        .frame(width: 120)
                        .foregroundColor(.green)
                    Text("Index: \(self.index)")
                        .foregroundColor(.white)
                        .font(.title)
                        .padding()
                    }
               }
               Text(bool ? "True" : "False")
                 .foregroundColor(.white)
                 .font(.title)
            }
            .mask(Background1()) 
        }
     }
   }