How to change the background color of the UIAlertController?

前端 未结 10 1441
耶瑟儿~
耶瑟儿~ 2020-11-30 03:49

Due to strange behavior of UIActionSheet in iOS 8, I have implemented UIAlertController with UIAction as buttons in it. I would like to change the entire background of the U

10条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-30 04:24

    Here is a UIAlertController extension that works on both iPad and iPhone. Cancel button will change from a dark colour to white automatically depending on what blurStyle is selected:

    extension UIAlertController {
    
        private struct AssociatedKeys {
            static var blurStyleKey = "UIAlertController.blurStyleKey"
        }
    
        public var blurStyle: UIBlurEffectStyle {
            get {
                return objc_getAssociatedObject(self, &AssociatedKeys.blurStyleKey) as? UIBlurEffectStyle ?? .extraLight
            } set (style) {
                objc_setAssociatedObject(self, &AssociatedKeys.blurStyleKey, style, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    
                view.setNeedsLayout()
                view.layoutIfNeeded()
            }
        }
    
        public var cancelButtonColor: UIColor? {
            return blurStyle == .dark ? UIColor(red: 28.0/255.0, green: 28.0/255.0, blue: 28.0/255.0, alpha: 1.0) : nil
        }
    
        private var visualEffectView: UIVisualEffectView? {
            if let presentationController = presentationController, presentationController.responds(to: Selector(("popoverView"))), let view = presentationController.value(forKey: "popoverView") as? UIView // We're on an iPad and visual effect view is in a different place.
            {
                return view.recursiveSubviews.flatMap({$0 as? UIVisualEffectView}).first
            }
    
            return view.recursiveSubviews.flatMap({$0 as? UIVisualEffectView}).first
        }
    
        private var cancelActionView: UIView? {
            return view.recursiveSubviews.flatMap({
                $0 as? UILabel}
            ).first(where: {
                $0.text == actions.first(where: { $0.style == .cancel })?.title
            })?.superview?.superview
        }
    
        public convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, blurStyle: UIBlurEffectStyle) {
            self.init(title: title, message: message, preferredStyle: preferredStyle)
            self.blurStyle = blurStyle
        }
    
        open override func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()
    
            visualEffectView?.effect = UIBlurEffect(style: blurStyle)
            cancelActionView?.backgroundColor = cancelButtonColor
        }
    }
    

    The following UIView extension is also needed:

    extension UIView {
    
        var recursiveSubviews: [UIView] {
            var subviews = self.subviews.flatMap({$0})
            subviews.forEach { subviews.append(contentsOf: $0.recursiveSubviews) }
            return subviews
        }
    }
    

    Example:

    let controller = UIAlertController(title: "Dark Alert Controller", message: nil, preferredStyle: .actionSheet, blurStyle: .dark)
    
    // Setup controller actions etc...
    
    present(controller, animated: true, completion: nil)
    

    iPhone:

    iPad:

提交回复
热议问题