【问题标题】:SwiftUI: modal Sheet hides ProgressViewSwiftUI:模态表隐藏 ProgressView
【发布时间】:2021-09-30 08:48:10
【问题描述】:

我试图在我的 SwiftUI 应用程序中拥有一个系统范围的进度条,所以我定义了这个视图(注意:我的目标是 iOS 13+):

import SwiftUI

struct LoadingView<Content>: View where Content: View {
    @Binding var isShowing: Bool
    var content: () -> Content

    var body: some View {
        GeometryReader { _ in
            ZStack {
                self.content()

                if self.isShowing {
                    VStack {
                        ActivityIndicator()
                        Text("Loading...")
                    }
                }
            }
        }
    }
}

struct ActivityIndicator: UIViewRepresentable {
    typealias UIView = UIActivityIndicatorView
    fileprivate var configuration = { (_: UIView) in }

    func makeUIView(context: UIViewRepresentableContext<Self>) -> UIView { UIView() }
    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<Self>) {
        uiView.startAnimating()
        configuration(uiView)
    }
}

并且像这样在 ContenView.swift 中使用

import SwiftUI

struct ContentView: View {
    @EnvironmentObject var myViewModel: MyViewModel

    var body: some View {
        let isLoading = Binding<Bool>(
            get: { self.myViewModel.isLoading },
            set: { _ in }
        )

        LoadingView(isShowing: isLoading) {
            NavigationView {
                Home()
            }
            .navigationViewStyle(StackNavigationViewStyle())
        }
    }
}

其中 MyViewModel 是一个非常标准的 ViewModel,带有一个用于 isLoading 的 @Published var,Home() 是应用程序的主要入口点。

每当在 MyViewModel 中触发 isLoading 的某些操作完成时,进度条就会正确显示(和隐藏)。

但是,如果我通过 NavigationView 中的一个视图或使用 ContentView 本身来呈现.sheet,无论它隐藏进度条是什么。

即使我使用内置 14+ ProgressView 问题仍然存在。

.Zindex() 也无济于事。

无论.sheet.alert 或 SwiftUI 上可用的任何覆盖视图,是否有任何方法可以让该视图在显示时始终位于顶部?

提前致谢!

【问题讨论】:

  • 无论如何,您的观察应该是预期的行为,因为工作表是 modal 视图。模态应该始终显示在“计算机”需要“人类”输入的任何其他视图之上。见wiki
  • @CouchDeveloper 我明白你的意思。但是,如果我用LoadingView 视图将我的视图主体包含在.sheet 中,进度条实际上会出现在模式的顶部。似乎在打开工作表时,Apple 选择以一种非常孤立的方式将两层分开。
  • 当然,当您在模态视图中显示加载指示器时,它会在位于顶部的模态视图中呈现。恕我直言,从用户体验的角度来看,有一个覆盖加载指示器的模式看起来很奇怪。应用程序不应该等到结果可用之前显示警报或工作表吗?
  • Sheet 用于输入一些数据,这些数据会触发 MyViewModel(以及 isLoading 属性),并且这些触发器不一定在工作表关闭时发生。所以我在这里描述的行为。让每个 .sheet 都有自己的加载器是一种方式。从用户体验的角度来看,我支持你,在这种情况下,也许全局 ZIndex 会是实用的,但我不确定这是否是一个好习惯
  • @CouchDeveloper 能否请您根据您在 cmets 中写下的考虑来回答这个问题,以便我给予您应得的荣誉?

标签: ios swift swiftui


【解决方案1】:

正如在 cmets 中已经写的那样,模态视图将显示在任何其他视图的顶部modal 视图旨在建立人机交流,或 dialog(因此,modal 视图经常被命名为“Dialog”)。

观察到工作表(模态视图)覆盖加载指示器是预期行为。

但是,IMO 问题中描述并在 cmets 中细化的问题,可以很好地解决,而不会破坏模态视图的行为:

当您想要显示尚未完成或什至完全不存在的数据时,您可能会显示“空白”屏幕,除此之外,让视图模型生成一个视图状态,说明视图应该显示“输入表”。

所以最初,用户会在空白屏幕上看到一个输入表单。

一旦用户输入并提交表单(将在视图模型中处理),输入表就会消失(由视图模型生成的视图状态控制),并显示它下面的“空白”视图。

因此,视图模型现在可以呈现另一个工作表,或者它意识到输入已完成。

一旦输入完成,视图模型就会加载数据,由于这可能需要一段时间,它会在视图状态中相应地反映这一点,例如使用“加载”状态或标志。视图会相应地呈现它,这是“空白”视图上方的加载指示器。

当视图模型接收到数据时,它会清除加载状态并相应地设置视图状态,同时传递数据。

视图现在呈现数据视图。

如果加载任务失败,视图模型将组成​​一个视图状态,其中内容“不存在”并带有错误信息。

视图再次呈现这一点,可能会在“空白”视图上方显示带有消息的警报,因为仍然没有数据。

确保用户可以关闭错误警报,并且视图模型通过删除“模态错误”状态来处理它,但内容仍然“不存在”。

现在,用户正盯着一个空白视图。您可以在此处嵌入错误消息,甚至添加“重试”按钮。在任何情况下,请确保用户可以离开该屏幕。

等等。 ;)

【讨论】:

    猜你喜欢
    • 2023-02-13
    • 1970-01-01
    • 2022-07-03
    • 2019-10-22
    • 2019-11-15
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    相关资源
    最近更新 更多