没有模糊视图效果的UIAlertController操作表

时间:2017-05-06 17:21:33

标签: ios objective-c swift uialertcontroller uivisualeffectview

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

但我不是动作组视图中模糊视图效果的忠实粉丝(见下面的截图)。

Action Sheet with Blurry View

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

  

UIAlertController类旨在按原样使用,不支持子类化。此类的视图层次结构是私有的,不得修改。

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

Instagram's fixed version

我找到删除它的唯一方法是通过UIAlertController的扩展名自行更新视图层次结构。

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()

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

Fixed action sheet

我在想什么......我的解决方案是否是实现这一目标的唯一途径?或者我有一些关于警报控制器外观的东西? 也许有一种更清洁的方法来完成这个结果?还有其他想法吗?

1 个答案:

答案 0 :(得分:1)

子类UIAlertController的继承比较容易。

想法是每次调用viewDidLayoutSubviews时都要遍历视图层次结构,删除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. 创建警报控制器。
  2. 设置按钮背景色: alertController.buttonBackgroundColor = .darkGray
  3. 自定义并显示控制器。

结果:

Result screenshot