如何仅在ScrollView中禁用滚动而不在内容视图中禁用滚动?

时间:2019-09-14 08:02:03

标签: ios swift swiftui

最近,我编写了一个小的SwiftUI库,该库可以旋转View数组并选择View。

Gif-1

但是发现了一个问题,我无法弄清楚在正常模式下如何在ScrollView中禁用滚动。

Gif-2

很遗憾,我试图将.disabled(true)放在ScrollView的末尾,这不仅禁用了滚动,而且还禁用了ScrollView中的所有视图。

这里是source code中的project

我应该添加什么修饰符来解决这个问题?

-已编辑-

我试图更改滚动轴,但是一旦滚动轴变为[],scrollview将重置其内容偏移量,想知道是否存在一种无需更改轴即可阻止滚动的方法。

-已解决-

最后,我只添加了一个DragGesture()来阻止滚动事件并正常工作。

3 个答案:

答案 0 :(得分:3)

我尝试使用Rob Mayoff提供的公认答案,但重置内容偏移量是建议方法的令人沮丧的缺点。

使用Introspect库(对于在SwiftDC上等待SwiftUI 2的用户,我建议向寻找SwiftKit API的UIKit级别控件的人推荐)-您可以访问基础的isScollEnabled布尔标志为SwiftUI的ScrollView提供动力的基础UIScrollView的像素并进行相应设置。更改isScollEnabled不会对contentOffset产生任何影响,并且其工作方式与应该的完全相同。

它可以像这样简单地实现:

struct TestView: View {
    @Binding var shouldScroll: Bool

    var body: some View {
        ScrollView {
            Text("Your content here").introspectScrollView { scrollView in
                scrollView.isScrollEnabled = shouldScroll
            }
        }
    }
}

Introspect库真的就是这么简单!

答案 1 :(得分:2)

如果要滚动视图,仅将inetpub作为滚动轴。否则,传递空集。

.horizontal

答案 2 :(得分:0)

我一直回到这个问题,对这里的任何答案都不满意。我发现有效的是创建一个自定义包装器来评估是否应该使用 ScrollView。这比我想象的要容易得多。

创建可预防的滚动视图

本质上我们想要一个可以切换滚动的自定义视图。使用绑定,任何使用我们视图的人都可以完全控制滚动功能。

请原谅我的命名,但我只能想到 PreventableScrollView :)

struct PreventableScrollView<Content>: View where Content: View {
    @Binding var canScroll: Bool
    var content: () -> Content
    
    var body: some View {
        if canScroll {
            ScrollView(.vertical, showsIndicators: false, content: content)
        } else {
            content()
        }
    }
}

基本上我们需要做的就是决定是将内容嵌入到 ScrollView 中还是直接返回它。非常简单。

我创建了一个演示来展示这如何处理动态内容以及随时切换的能力。当我添加项目时,它也会切换滚动。

如果你有兴趣,这里是代码。

struct DemoView: View {
    @State private var canScroll: Bool = false
    let allColors: [UIColor] = [.purple, .systemPink, .systemGreen, .systemBlue, .black, .cyan, .magenta, .orange, .systemYellow, .systemIndigo, .systemRed]
    @State var colors: [UIColor] = [.white]
    
    var body: some View {
        VStack {
            Spacer()
            VStack {
                PreventableScrollView(canScroll: $canScroll) {
                    ForEach(colors.indices, id: \.self) { index in
                        Rectangle().fill().foregroundColor(Color(colors[index]))
                            .frame(height: 44)
                            .cornerRadius(8)
                    }
                }.fixedSize(horizontal: false, vertical: true)
                HStack {
                    Spacer()
                    Toggle(isOn: $canScroll, label: {
                        Text("Toggle Scroll")
                    }).toggleStyle(SwitchToggleStyle(tint: .orange))
                }.padding(.top)
            }
            .textFieldStyle(RoundedBorderTextFieldStyle())
            .padding()
            .background(Rectangle().fill().foregroundColor(Color(UIColor.secondarySystemFill)).cornerRadius(8))
            HStack {
                Button(action: {
                    addField()
                }, label: {
                    Image(systemName: "plus")
                }).padding()
            }
        }
            .padding()
    }
    
    func addField() {
        canScroll.toggle()
        colors.append(allColors.randomElement()!)
    }
}