如何更改UIAlertController的背景颜色?

时间:2014-11-11 11:08:39

标签: ios objective-c uiactionsheet uialertcontroller

由于UIActionSheet在iOS 8中的奇怪行为,我已经将UIAlertController与UIAction一起实现为按钮。我想改变UIAlertController的整个背景。但我找不到任何办法。

甚至尝试过,

actionController.view.backgroundColor = [UIColor blackColor];
但是没有帮助我。关于这方面的任何意见都会很明显。

提前致谢。

10 个答案:

答案 0 :(得分:38)

你必须深入了解一些观点:

let subview = actionController.view.subviews.first! as UIView
let alertContentView = subview.subviews.first! as UIView
alertContentView.backgroundColor = UIColor.blackColor()

也许你想保持原来的角落半径:

 alertContentView.layer.cornerRadius = 5;

抱歉“Swifting”,但我不熟悉Objective-C。我希望这是类似的。

当然,更改动作的标题颜色也很重要。不幸的是我不知道,如何分别设置动作的颜色。但是,这是如何更改所有按钮文本颜色:

actionController.view.tintColor = UIColor.whiteColor();

编辑:

UIAlertController 的角半径自此答案发布以来已发生变化!替换这个:

 alertContentView.layer.cornerRadius = 5;

到此:

 actionContentView.layer.cornerRadius = 15

答案 1 :(得分:19)

也许你喜欢在黑暗模式下使用模糊效果。这是一个非常简单的方法:

ResultSet rs = statement.executeQuery("SELECT isAdmin FROM users WHERE name LIKE '"+nameValue+"' AND password LIKE '"+passValue");
if(rs.next()){
    if(rs.getBoolean()){
    // redirect to admin.jsp
    }
    else {
    // redirect to user.jsp
    }
} else {
 // user or password invalid
}

答案 2 :(得分:15)

我找到了一种破解方法。首先,您需要一个扩展程序,以便在UIVisualEffectView

中搜索UIAlertController
extension UIView
{
    func searchVisualEffectsSubview() -> UIVisualEffectView?
    {
        if let visualEffectView = self as? UIVisualEffectView
        {
            return visualEffectView
        }
        else
        {
            for subview in subviews
            {
                if let found = subview.searchVisualEffectsSubview()
                {
                    return found
                }
            }
        }

        return nil
    }
}

重要:您必须在调用presentViewController后调用此函数,因为只有在加载视图控制器后才会将视觉效果视图插入到位。然后,您可以将与其关联的效果更改为暗模糊效果:

self.presentViewController(actionController, animated: true, completion: nil)

if let visualEffectView = actionController.view.searchVisualEffectsSubview()
{
    visualEffectView.effect = UIBlurEffect(style: .Dark)
}

这是最终结果:

demo picture

老实说我很惊讶它的工作原理!我想这可能是Apple忘记添加的内容。此外,我还没有 通过批准通过应用程序" hack" (这不是一个黑客,因为我们只使用公共API),但我确信这不会成为一个问题。

答案 3 :(得分:8)

用于Swift 3 / Swift 4

let subview =(alert.view.subviews.first?.subviews.first?.subviews.first!)! as UIView

            subview.backgroundColor = UIColor(red: (145/255.0), green: (200/255.0), blue: (0/255.0), alpha: 1.0)

            alert.view.tintColor = UIColor.black

enter image description here

答案 4 :(得分:5)

Swift3

与swift2比较进入另一个图层

[self presentViewController:yourImagePickerController animated:YES completion:NULL];

答案 5 :(得分:4)

func Alert(View: ViewController, Title: String, TitleColor: UIColor, Message: String, MessageColor: UIColor, BackgroundColor: UIColor, BorderColor: UIColor, ButtonColor: UIColor) {

    let TitleString = NSAttributedString(string: Title, attributes: [NSFontAttributeName : UIFont.systemFontOfSize(15), NSForegroundColorAttributeName : TitleColor])
    let MessageString = NSAttributedString(string: Message, attributes: [NSFontAttributeName : UIFont.systemFontOfSize(15), NSForegroundColorAttributeName : MessageColor])

    let alertController = UIAlertController(title: Title, message: Message, preferredStyle: .Alert)

    alertController.setValue(TitleString, forKey: "attributedTitle")
    alertController.setValue(MessageString, forKey: "attributedMessage")

    let okAction = UIAlertAction(title: "OK", style: .Default) { (action) in

    }

    let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: nil)

    alertController.addAction(okAction)
    alertController.addAction(cancelAction)


    let subview = alertController.view.subviews.first! as UIView
    let alertContentView = subview.subviews.first! as UIView
    alertContentView.backgroundColor = BackgroundColor
    alertContentView.layer.cornerRadius = 10
    alertContentView.alpha = 1
    alertContentView.layer.borderWidth = 1
    alertContentView.layer.borderColor = BorderColor.CGColor


    //alertContentView.tintColor = UIColor.whiteColor()
    alertController.view.tintColor = ButtonColor

    View.presentViewController(alertController, animated: true) {
        // ...
    }
}

答案 6 :(得分:4)

这是一个适用于iPad和iPhone的UIAlertController扩展程序。根据选择的blurStyle,取消按钮将自动从深色变为白色:

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
    }
}

还需要以下UIView扩展程序:

extension UIView {

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

示例:

let controller = UIAlertController(title: "Dark Alert Controller", message: nil, preferredStyle: .actionSheet, blurStyle: .dark)

// Setup controller actions etc...

present(controller, animated: true, completion: nil)

iPhone:

enter image description here

iPad:

enter image description here

答案 7 :(得分:1)

目标 - C代码可能会像。

UIAlertController * alert=[UIAlertController alertControllerWithTitle:@"Title"
                                                              message:@"Message"
                                                       preferredStyle:UIAlertControllerStyleAlert];
UIView *firstSubview = alert.view.subviews.firstObject;
UIView *alertContentView = firstSubview.subviews.firstObject;
for (UIView *subSubView in alertContentView.subviews) {
    subSubView.backgroundColor = [UIColor colorWithRed:255/255.0f green:255/255.0f blue:255/255.0f alpha:1.0f];
}
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){
   //Close Action
}];
[alert addAction:cancelAction];
[self presentViewController:alert animated:YES completion:nil];

答案 8 :(得分:0)

我发现的最佳决定(侧面没有白色斑点)

Link to original answerVadim Akhmerov

答案:

子类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. 创建警报控制器(现在使用AlertController代替UIAlertController)

让testAlertController = AlertController(标题:无,消息:无,preferredStyle:.actionSheet)

  1. 在自定义类“ AlertController”上设置背景颜色:

var buttonBackgroundColor:UIColor = .darkGray

答案 9 :(得分:-1)

您可以使用外观代理。

[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setBackgroundColor:[UIColor blackColor]];

这似乎适用于除作为行动单提交时的取消行动。