首页 > 解决方案 > 如何防止在 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 的答案记住我可能很难理解,我将不胜感激。帮助!

标签: swiftswiftuiscrollview

解决方案


一个可能的解决方案是删除或修改 Apple Docs 中的 .mask(Background()), mask 行“渲染系统应用于指定视图的视图”。“当您想将另一个视图的 alpha(不透明度)值应用到当前视图时,请使用 mask(_:)。” 应用具有相同背景的蒙版,并在此背景视图内几何阅读器影响滚动视图内的按钮。

如果您评论 //.mask(Background) 对我来说很好,并且也可以很好地显示白色边框。另一种使用掩码在 ScrollView 上添加 VStack 并在没有 Geometry 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()) 
        }
     }
   }

推荐阅读