ios - 没有模糊 View 效果的 UIAlertController 操作表

标签 ios objective-c swift uialertcontroller uivisualeffectview

我正在使用 UIAlertController 进行一些操作。

但我不太喜欢操作组 View 中的模糊 View 效果(请参见下面的屏幕截图)。

Action Sheet with Blurry View

我正在尝试消除这种模糊效果。我在网上做了一些研究,但在 UIAlertController 中找不到任何 API 可以消除这种模糊效果。另外,根据他们的苹果文档 here :

The UIAlertController class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.

我看到 Instagram 也消除了这种模糊的 View 效果:

Instagram's fixed version

我能找到的删除它的唯一方法是通过 UIAlertController 的扩展自己更新 View 层次结构。

extension UIAlertController {
    @discardableResult private func findAndRemoveBlurEffect(currentView: UIView) -> Bool {
        for childView in currentView.subviews {
            if childView is UIVisualEffectView {
                childView.removeFromSuperview()
                return true
            } else if String(describing: type(of: childView.self)) == "_UIInterfaceActionGroupHeaderScrollView" {
                // One background view is broken, we need to make sure it's white.
                if let brokenBackgroundView = childView.superview {
                    // Set broken brackground view to a darker white
                    brokenBackgroundView.backgroundColor = UIColor.colorRGB(red: 235, green: 235, blue: 235, alpha: 1)
                }
            }
            findAndRemoveBlurEffect(currentView: childView)
        }
        return false
    }
}

let actionSheetController = UIAlertController(title: title, message: nil, preferredStyle: .actionSheet)
actionSheetController.view.tintColor = .lightBlue
actionSheetController.removeBlurryView()

这很好用,它消除了我的模糊 View 效果:

Fixed action sheet

我想知道的是...我的解决方案是实现该目标的唯一方法吗?或者我在 Alert Controller 外观上遗漏了什么? 也许有一种更简洁的方法可以准确地实现该结果?还有其他想法吗?

最佳答案

子类化 UIAlertController 更容易。

想法是在每次调用 viewDidLayoutSubviews 时遍历 View 层次结构,移除 UIVisualEffectView 的效果并更新它们的 backgroundColor:

class AlertController: UIAlertController {

    /// Buttons background color.
    var buttonBackgroundColor: UIColor = .darkGray {
        didSet {
            // Invalidate current colors on change.
            view.setNeedsLayout()
        }
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        // Traverse view hierarchy.
        view.allViews.forEach {
            // If there was any non-clear background color, update to custom background.
            if let color = $0.backgroundColor, color != .clear {
                $0.backgroundColor = buttonBackgroundColor
            }
            // If view is UIVisualEffectView, remove it's effect and customise color.
            if let visualEffectView = $0 as? UIVisualEffectView {
                visualEffectView.effect = nil
                visualEffectView.backgroundColor = buttonBackgroundColor
            }
        }

        // Update background color of popoverPresentationController (for iPads).
        popoverPresentationController?.backgroundColor = buttonBackgroundColor
    }

}


extension UIView {

    /// All child subviews in view hierarchy plus self.
    fileprivate var allViews: [UIView] {
        var views = [self]
        subviews.forEach {
            views.append(contentsOf: $0.allViews)
        }

        return views
    }

}

用法:

  1. 创建警报 Controller 。
  2. 设置按钮背景颜色: alertController.buttonBackgroundColor = .darkGray
  3. 自定义并呈现 Controller 。

结果:

Result screenshot

关于ios - 没有模糊 View 效果的 UIAlertController 操作表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43823331/

相关文章:

ios - 无法将类型 'CustomProfileCell' 的返回表达式转换为返回类型 'UITableViewCell'

来自 Objective-C iPhone 应用程序的 PHP MySQL 请求未发布到我的表

ios - SWRevealViewController 中的后退按钮

ios - 如何区分didFinishPickingMediaWithInfo中的UIImagePickerController

ios - 在Flutter中安装 native iOS Pod

ios - 在 IOS 项目中放置 .txt 文件并从中读取的位置

swift - 如何在 Swift 中创建 Hashable 集合

iphone - 在表格 View 中选择后如何将数据传递到详细 View ?

iphone - 在后台持续运行应用程序

ios - 将多个图像发送到 Web 服务器