ios 块触及任何自定义弹出窗口时显示

qvtsj1bj  于 2023-05-19  发布在  iOS
关注(0)|答案(3)|浏览(135)

用户可以通过单击导航栏中的按钮将数据上传到我的Swift 5/Xcode 12.4应用程序中的服务器。当这发生时(在后台线程中异步),我正在显示一个自定义弹出窗口,并且没有一个常规按钮(包括导航栏中的按钮)应该是可点击的:

static func showIndicator(view: UIView) {
    let parentView = UIView(frame: view.frame)
    parentView.backgroundColor = UIColor.red.withAlphaComponent(0.5) //red only for testing, going to be set to 0.0 later
        
    let indicatorContainer = UIView()
    let width = 80
    let height = 80
        
    indicatorContainer.frame = CGRect(x: 0, y: 0, width: width, height: height)
    indicatorContainer.center = view.center
    indicatorContainer.backgroundColor = UIColor.darkGray.withAlphaComponent(0.97)
    indicatorContainer.layer.cornerRadius = 8
    indicatorContainer.clipsToBounds = true
        
    let indicatorView = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large)
    indicatorView!.center = CGPoint(x: width/2, y: height/2)
        
    indicatorContainer.addSubview(indicatorView!)
    parentView.addSubview(indicatorContainer)
    view.addSubview(parentView)
    indicatorView!.startAnimating()
}

UIViewController调用:

Toaster.showIndicator(view: self.view)

这使得它不可能触摸按钮,...在常规的UIView中,它没有覆盖导航栏,理论上用户可以第二次启动上传过程(以及其他事情),这并不好。我发现了两种方法来防止这种情况发生:
1.使用uploadButton.isEnabled = false暂时禁用导航栏中的按钮。这具有按钮变成灰色的缺点。
1.用一个不可见的UIView覆盖整个区域,包括导航栏,但这也覆盖了状态栏,我不确定是否可以像这样简单地访问窗口:

static func showIndicator(view: UIView) {
     let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow })!
     let parentView = UIView(frame: window.frame)

     ...

     parentView.addSubview(indicatorContainer)
     window.addSubview(parentView)
     indicatorView!.startAnimating()
 }

我知道userInteractionEnabled,但你不能把它用于UIBarButtonItem,而且弹出窗口下面有太多其他可点击的UI元素,不能暂时禁用它们。
在应用程序中阻止按钮按下任何东西(=在弹出视图下面),而其他不应该被用户交互中断的事情正在发生时,首选的方法是什么?

xyhw6mcr

xyhw6mcr1#

问得好,看看视图层次结构

导航栏项目位于Toaster的前面,为了覆盖UIKit中的导航栏,您可以使用应用委托的window属性在导航栏上方添加自定义视图。这就是大多数第三方“烤面包机”框架(如MBProgressHUD)所做的。
因此,阻止烤面包机后面的每个触摸事件所需的最小变化是

// instead of add parent view to view, add it to keyWindow
    // view.addSubview(parentView)
    parentView.tag = 999 // set a tag to remove the view from the window's subviews later
    guard let window = UIApplication.shared.keyWindow else { return }
    window.addSubview(parentView)
    indicatorView.startAnimating()
kokeuurv

kokeuurv2#

你可以使用类似这个函数的东西,它检查UIViewController中的所有视图,尝试转换它们以禁用用户交互。您可以添加任意多的类型。

func toggleEditEnabled(editAllowed: Bool) {
    for view in self.view.allSubviews {
        if let button = view as? UIButton {
            button.isUserInteractionEnabled = editAllowed
        } else if let textField = view as? UITextField {
            textField.isUserInteractionEnabled = editAllowed
        }
    }
}

该函数可以这样使用:
启用交互:toggleEditEnabled(editAllowed:真)
禁用交互:toggleEditEnabled(editAllowed:false)

ogq8wdun

ogq8wdun3#

在窗口上添加视图是最好的UI解决方案。从iOS 13开始,您可以通过self.view.window访问当前的window
或者试试下面这个更快、更简单、更稳定的解决方案。只需在ViewController中创建一个标志变量,...
例如:var isUploading = false

func uploadImage(done: @escaping (UploadedURL) -> Void) {

    if self.isUploading { return } // Block users from spamming
    self.isUploading = true // Start uploading here
    // Show your popup here
    
    UploadManager.current.upload(file) {[weak self] result in
        self?.isUploading = false
        DispatchQueue.main.async {
            // Hide your Popup here
        }
        done(result)
    }
}

相关问题