UIAlertController Action Sheet without Blurry View Effect

ぐ巨炮叔叔 提交于 2020-01-13 04:41:08

问题


I'm using UIAlertController for some actions.

But I'm not a big fan of the Blurry View Effect in the actions group view (see screenshot below).

I'm trying to remove this blurry effect. I made some research online, and I couldn't find any API in UIAlertController that allows to remove this blurry effect. Also, according to their apple doc 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.

I see that Instagram also removes this blurry view effect :

The only way I could find to remove it is to update the view hierarchy myself via an extension of 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()

This worked fine, it removed my blurry view effect:

What I'm wondering... Is my solution the only way to accomplish that? Or there is something that I'm missing about the Alert Controller appearance? Maybe there is a cleaner way to accomplish exactly that result? Any other ideas?


回答1:


It is easier to subclass UIAlertController.

The idea is to traverse through view hierarchy each time viewDidLayoutSubviews gets called, remove effect for UIVisualEffectView's and update their 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
    }

}

Usage:

  1. Create alert controller.
  2. Set buttons background color: alertController.buttonBackgroundColor = .darkGray
  3. Customise and present controller.

Result:



来源:https://stackoverflow.com/questions/43823331/uialertcontroller-action-sheet-without-blurry-view-effect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!