SwiftUI的Modifier实现Toast和Loading

样例

通常要实现一个toast弹出逻辑,嵌套一个zstack,往原本的内容上方叠一个toast就行了

struct TestToast: View {
    @State var presentingToast = false
    var body: some View {
        ZStack {
            Button("show toast") {
                presentingToast = true
                DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                    presentingToast = false
                }
            }
            if presentingToast {
                /// toastBody...
                Text("hello toast")
            }
        }
    }
}

如果要在一个很庞大的视图外侧中嵌套zstack,必然要把原本的view代码整体往右缩进一级,非常麻烦

其中一个简单的方案是使用ViewModifier,使用起来就避免了直接嵌套zstack带来的代码缩进麻烦

Button("show toast") {
    presentingToast = true
}
.toast(isPresenting: $presentingToast, text: "Hello Toast")

声明这样一个类型遵循ViewModifier协议,需要实现func body(content: Content) -> some View方法,其中content就是上文的老内容,在此基础上添加新内容

这里的实现是在ViewModifier内间接嵌套ZStack,使得外层保持美观

extension View {
    public func toast(isPresenting: Binding, text: String) -> some View {
        modifier(ToastModifier(isPresent: isPresenting, text: text))
    }
}

struct ToastModifier: ViewModifier {
    @Binding var isPresent: Bool
    var text: String
    
    func body(content: Content) -> some View {
        ZStack {
            content
            if isPresent {
                /// toastBody
                Text("hello toast")
                    .onAppear {
                        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                            isPresent = false
                        }
                    }
            }
        }
    }
}

LoadingToast同理,改动toastBody的内容即可

你可能感兴趣的:(SwiftUI的Modifier实现Toast和Loading)