ios 如何更改 UIAlertController 的背景颜色?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26863460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:34:58  来源:igfitidea点击:

How to change the background color of the UIAlertController?

iosobjective-cuiactionsheetuialertcontroller

提问by GJDK

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 UIAlertController. But I can't find any ways to do it.

由于 iOS 8 中 UIActionSheet 的奇怪行为,我已经实现了 UIAlertController 和 UIAction 作为其中的按钮。我想更改 UIAlertController 的整个背景。但我找不到任何方法来做到这一点。

Tried even with,

甚至尝试过,

actionController.view.backgroundColor = [UIColor blackColor];

But didn't help me out. Any inputs on this regard will be appreciable.

但没有帮助我。在这方面的任何投入都将是可观的。

Thanks in advance.

提前致谢。

回答by nischtname

You have to step some views deeper:

您必须更深入地了解一些视图:

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

And maybe you want to keep original corner radius:

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

 alertContentView.layer.cornerRadius = 5;

Sorry for the "Swifting"but i'm not familiar with Objective-C. I hope that's similar.

对不起“Swifting”,但我不熟悉Objective-C。我希望这是相似的。

Of course it's also important to change the title color of the actions. Unfortunately I don't know, how to set the color of actions separately. But this is, how you change all button text colors:

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

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

EDIT:

编辑:

The corner radius of the UIAlertControllerhas changed since this answer's been posted! Replace this:

自从发布此答案以来,UIAlertController的角半径已更改!替换这个:

 alertContentView.layer.cornerRadius = 5;

to this:

对此:

 actionContentView.layer.cornerRadius = 15

回答by Jeanette Müller

maybe you like the use the blur effect in the dark mode. Here is a very easy way to get this:

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

UIVisualEffectView.appearance(whenContainedInInstancesOf: [UIAlertController.classForCoder() as! UIAppearanceContainer.Type]).effect = UIBlurEffect(style: .dark)

回答by Bruno Philipe

I have found a hack-ish way of doing it. First you need an extension to allow you to search for the UIVisualEffectViewinside the UIAlertController:

我找到了一种黑客式的方法。首先,你需要的扩展,使您可以搜索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
    }
}

Important: You have to call this function aftercalling presentViewController, because only after loading the view controller that the visual effects view is inserted into place. Then you can change the effect associated with it to a dark blur effect:

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

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

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

And this is the final result:

这是最终的结果:

demo picture

演示图片

I am honestly surprised myself how well it works! I think this is probably something Apple forgot to add. Also, I haven't yetpassed an App through approval with this "hack" (it isn't a hack because we're only using public APIs), but I'm confident there won't be a problem.

老实说,我自己很惊讶它的效果如何!我认为这可能是 Apple 忘记添加的内容。此外,我还没有还没有通过这个“黑客”(这是不是黑客攻击,因为我们只使用公共API)批准通过了一个应用程序,但我相信不会有问题。

回答by Shakeel Ahmed

for Swift 3/ Swift 4

适用于 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.

在此处输入图片说明.

回答by Mark Bourke

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

这是一个UIAlertController适用于 iPad 和 iPhone的扩展程序。取消按钮会根据选择的 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({
extension UIView {

    var recursiveSubviews: [UIView] {
        var subviews = self.subviews.flatMap({
let controller = UIAlertController(title: "Dark Alert Controller", message: nil, preferredStyle: .actionSheet, blurStyle: .dark)

// Setup controller actions etc...

present(controller, animated: true, completion: nil)
}) subviews.forEach { subviews.append(contentsOf:
    let subview1 = alert.view.subviews.first! as UIView
    let subview2 = subview1.subviews.first! as UIView
    let view = subview2.subviews.first! as UIView

    subview.backgroundColor = backgroundColor
    view.backgroundColor = backgroundColor
    view.layer.cornerRadius = 10.0

    // set color to UILabel font
    setSubviewLabelsToTextColor(textColor, view: view)

    // set font to alert via KVC, otherwise it'll get overwritten
    let titleAttributed = NSMutableAttributedString(
        string: alert.title!,
        attributes: [NSFontAttributeName:UIFont.boldSystemFont(ofSize: 17)])
    alert.setValue(titleAttributed, forKey: "attributedTitle")

    let messageAttributed = NSMutableAttributedString(
        string: alert.message!,
        attributes: [NSFontAttributeName:UIFont.systemFont(ofSize: 13)])
    alert.setValue(messageAttributed, forKey: "attributedMessage")

    // set the buttons to non-blue, if we have buttons
    if let buttonColor = buttonColor {
        alert.view.tintColor = buttonColor
    }
.recursiveSubviews) } return subviews } }
as? UIVisualEffectView}).first } return view.recursiveSubviews.flatMap({
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) {
        // ...
    }
}
as? UIVisualEffectView}).first } private var cancelActionView: UIView? { return view.recursiveSubviews.flatMap({
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];
as? UILabel} ).first(where: {
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 = 
[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setBackgroundColor:[UIColor blackColor]];
.backgroundColor, color != .clear { ##代码##.backgroundColor = buttonBackgroundColor } // If view is UIVisualEffectView, remove it's effect and customise color. if let visualEffectView = ##代码## 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: ##代码##.allViews) } return views } }
.text == actions.first(where: { ##代码##.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 UIViewextension is also needed:

UIView还需要以下扩展:

##代码##

Example:

例子:

##代码##

iPhone:

苹果手机:

enter image description here

在此处输入图片说明

iPad:

iPad:

enter image description here

在此处输入图片说明

回答by Leandro Jiao

Swift3

斯威夫特3

Step into one more layer compare with swift2

与swift2相比,再进一层

##代码##

回答by user2643679

##代码##

回答by Yogesh Tarsariya

For Objective - C Code May be Like.

对于目标 - C 代码可能就像。

##代码##

回答by Bandyliuk

The best decision that i found (without white spots on the sides)

我发现的最佳决定(两侧没有白点)

Link to original answerby Vadim Akhmerov

链接到原来的答案瓦迪姆Akhmerov

Answer:

回答:

It is easier to subclass UIAlertController.

子类化更容易UIAlertController

The idea is to traverse through view hierarchy each time viewDidLayoutSubviewsgets called, remove effect for UIVisualEffectView's and update their backgroundColor:

这个想法是在每次viewDidLayoutSubviews被调用时遍历视图层次结构,删除UIVisualEffectView's 的效果并更新它们backgroundColor

##代码##

Usage:

用法:

  1. Create alert controller(use now AlertController instead UIAlertController)
  1. 创建警报控制器(现在使用 AlertController 而不是 UIAlertController)

let testAlertController = AlertController(title: nil, message: nil, preferredStyle: .actionSheet)

让 testAlertController = AlertController(title: nil, message: nil, preferredStyle: .actionSheet)

  1. Set background color on custom class "AlertController":
  1. 在自定义类“AlertController”上设置背景颜色:

var buttonBackgroundColor: UIColor = .darkGray

var buttonBackgroundColor: UIColor = .darkGray

回答by Paul Kite

You can use the appearance proxy.

您可以使用外观代理。

##代码##

This seems to apply for all but the cancel action when presenting as an action sheet.

当作为操作表呈现时,这似乎适用于除取消操作之外的所有操作。