简体   繁体   English

有条件地在视图 SwiftUI 内包装代码

[英]Conditionally wrap code inside view SwiftUI

I want to make my code inside a scrollview based on a boolean我想在基于 boolean 的滚动视图中制作我的代码

Something like this:像这样的东西:

 ScrollView{
    
          Vstack {
                
         }
         
           Hstack {
           
            }
    
    }.isWrapped(true)

So if the bool is true, the content is wrapped inside a ScrollView, if not, I just get the content as is.因此,如果 bool 为真,则内容将包装在 ScrollView 中,如果不是,我将按原样获取内容。 (without the scrollView parent) (没有 scrollView 父级)

I tried with multiples way, the only thing I see as possible is 2 blocks of code, not good practice thought.我尝试了多种方式,我看到的唯一可能是 2 块代码,不是很好的实践思想。

Because of the nature of SwiftUI, you can't remove the parent without removing children.由于 SwiftUI 的性质,您无法在不移除子项的情况下移除父项。 As you mentioned in your edit, this will require two blocks of code.正如您在编辑中提到的,这将需要两个代码块。 But, you can make it much more friendly in two different ways.但是,您可以通过两种不同的方式使其更加友好。


The first way is a reusable component.第一种方式是可重用组件。 It takes a Binding isVisible variable and the content.它需要一个 Binding isVisible变量和内容。

struct ConditionalScrollView<Content: View>: View {
    @Binding private var isVisible: Bool
    private var builtContent: Content

    init(isVisible: Binding<Bool>, content: () -> Content) {
        self._isVisible = isVisible
        builtContent = content()
    }

    var body: some View {
        if isVisible {
            ScrollView { builtContent }
        } else {
            builtContent
        }
    }
}

To use this new component is to simply replace the use of ScrollView in the area that you want to manually adjust.使用这个新组件,就是简单的在想要手动调整的区域替换使用ScrollView IE: IE:

struct ContentView: View {
    @State var isVisible = true

    var body: some View {
        ConditionalScrollView(isVisible: $isVisible) {
            Text("Hello, world!")
                .padding()
        }
    }
}

But this is not your only option.但这不是您唯一的选择。


If you want to keep things as simple as possible, you can achieve this using a simple ViewBuilder .如果您想让事情尽可能简单,您可以使用简单的ViewBuilder来实现。 Create the view you don't want to change inside the ViewBuilder , and then create a condition around the ScrollView , all the while placing the variable as the content.ViewBuilder中创建您不想更改的视图,然后在ScrollView周围创建一个条件,同时将变量作为内容。 It would look as follows:它看起来如下:

struct ContentView: View {
    @State private var isVisible = true

    @ViewBuilder private var mainContent: some View {
        Text("Hello, world!")
            .padding()
    }

    var body: some View {
        if isVisible {
            ScrollView { mainContent }
        } else {
            mainContent
        }
    }
}

As you've probably come to realize, this is one of the limitations of SwiftUI.您可能已经意识到,这是 SwiftUI 的限制之一。 But it can be considered a strength because you will always know if a view's parent is there or not.但这可以被认为是一种优势,因为您将始终知道视图的父级是否存在。

I hope this little tidbit helped, happy coding!我希望这个小花絮有所帮助,快乐的编码!

You can also make it even easier:您还可以使它更容易:

@State var isWraped : bool = true

var body: some View {
   if isWrapped {
     ScrollView {
          YourView()
     }
       else {
          YourView()
     }

One way is to always use a ScrollView , but tell it not to scroll.一种方法是始终使用ScrollView ,但告诉它不要滚动。 If you pass an empty set as the first argument to ScrollView , it won't scroll.如果您将空集作为第一个参数传递给ScrollView ,它将不会滚动。

ScrollView(shouldScroll ? .vertical : []) {
    // content here
}

Another way is to extract the content back out of the ScrollView in your proposed isWrapped modifier, like this:另一种方法是在您建议的isWrapped修饰符中从ScrollView中提取内容,如下所示:

extension ScrollView {
    @ViewBuilder
    func isWrapped(_ flag: Bool) -> some View {
        if flag { self }
        else { self.content }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM