ios 如何在 iOS9 中更改 UIAlertController 按钮文本颜色?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32856892/
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 07:52:43  来源:igfitidea点击:

How to change UIAlertController button text colour in iOS9?

iosobjective-cuialertcontroller

提问by RayChen

The question is similar to iOS 8 UIActivityViewController and UIAlertController button text color uses window's tintColorbut in iOS 9.

该问题类似于iOS 8 UIActivityViewController 和 UIAlertController 按钮文本颜色使用窗口的 tintColor但在 iOS 9 中。

I have a UIAlertController and the dismiss button keeps white colour even I have tried to set

我有一个 UIAlertController 并且即使我尝试设置,关闭按钮也保持白色

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

UIAlertController *strongController = [UIAlertController alertControllerWithTitle:title
                                                             message:message
                                                      preferredStyle:preferredStyle];
strongController.view.tintColor = [UIColor black];

回答by dbart

I've run into something similar in the past and the issue seems to stem from the fact that the alert controller's view isn't ready to accept tintColorchanges before it's presented. Alternatively, try setting the tint color AFTERyou present your alert controller:

我过去遇到过类似的事情,这个问题似乎源于这样一个事实,即警报控制器的视图tintColor在呈现之前还没有准备好接受更改。或者,尝试在您呈现警报控制器设置色调颜色:

[self presentViewController:strongController animated:YES completion:nil];
strongController.view.tintColor = [UIColor black];

回答by Neil Smith

In Swift 3.x:

在 Swift 3.x 中:

I found the following to work effectively. I call this at app launch .

我发现以下方法可以有效地工作。我在应用启动时调用它。

UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = UIColor.black

So this would change the tint color of all UIAlertViewController button labels in your app globally. The only button label color it doesn't change are those which have a UIAlertActionStyle of destructive.

因此,这将全局更改应用程序中所有 UIAlertViewController 按钮标签的色调。唯一不会改变的按钮标签颜色是具有破坏性 UIAlertActionStyle 的按钮标签颜色。

回答by MAhipal Singh

Objective-C

目标-C

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title text"  message:@"Message text"  preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
//code here…
}];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"Later" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
//code here….
}];
[ok setValue:[UIColor greenColor] forKey:@"titleTextColor"];
[cancel setValue:[UIColor redColor] forKey:@"titleTextColor"];
[alertController addAction:ok];
[alertController addAction:cancel];
[alertController.view setTintColor:[UIColor yellowColor]];
[self presentViewController:alertController animated:YES completion:nil];

Swift 3

斯威夫特 3

let alertController = UIAlertController(title: "Title text", message: "Message text", preferredStyle: .alert)
let ok = UIAlertAction(title: "Yes" , style: .default) { (_ action) in
             //code here…
        }
let cancel = UIAlertAction(title: "Later" , style: .default) { (_ action) in
            //code here…
        }
ok.setValue(UIColor.green, forKey: "titleTextColor")
cancel.setValue(UIColor.red, forKey: "titleTextColor")
alertController.addAction(ok)
alertController.addAction(cancel)
alertController.view.tintColor = .yellow
self.present(alertController, animated: true, completion: nil)

回答by Mike Taverne

I was able to solve this by subclassing UIAlertController:

我能够通过子类化来解决这个问题UIAlertController

class MyUIAlertController: UIAlertController {

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

        //set this to whatever color you like...
        self.view.tintColor = UIColor.blackColor()
    }
}

This survives a device rotation while the alert is showing.

在显示警报时,这会在设备轮换中幸存下来。

You also don't need to set the tintColor after presenting the alert when using this subclass.

使用此子类时,您也不需要在显示警报后设置 tintColor。

Though it isn't necessary on iOS 8.4, this code does work on iOS 8.4 as well.

尽管在 iOS 8.4 上不是必需的,但此代码也适用于 iOS 8.4。

Objective-C implementation should be something like this:

Objective-C 的实现应该是这样的:

@interface MyUIAlertController : UIAlertController
@end

@implementation MyUIAlertController
-(void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    //set this to whatever color you like...
    self.view.tintColor = [UIColor blackColor];
}
@end

回答by Mike M

swift3

迅捷3

Tried to use UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = MyColorbut this prevents other items unrelated to the UIAlertControllerfrom tintColor configuration. I saw it while trying to change the color of navigation bar button items.

尝试使用,UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = MyColor但这会阻止与UIAlertControllerfrom tintColor 配置无关的其他项目。我在尝试更改导航栏按钮项目的颜色时看到了它。

I switched to an extension (based on Mike Taverne's response above) and it works great.

我切换到了一个扩展(基于上面 Mike Taverne 的回复)并且效果很好。

extension UIAlertController {

override open func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    //set this to whatever color you like...
    self.view.tintColor = MyColor
}
}

回答by Brendan

After alot of research, I found out how to make this work:

经过大量研究,我发现了如何使这项工作:

let cancelButton = UIAlertAction(title: button, style: UIAlertAction.Style.cancel, handler: { (action) in alert.dismiss(animated: true, completion: nil)
    })

    cancelButton.setValue(UIColor.systemBlue, forKey: "titleTextColor")
    alert.addAction(cancelButton)

Just change the UIColor.systemBlue to what ever color you want, and it will make just that button a special color. I made this example (I created 3 UIAlertActions to make it.):
enter image description here

只需将 UIColor.systemBlue 更改为您想要的任何颜色,它就会使该按钮成为特殊颜色。我做了这个例子(我创建了 3 个 UIAlertActions 来实现它。):
在此处输入图片说明

With just UIAlertAction.Style.whatever, it can only make it blue or red. If you change the UIColor, it will make it any color you want!

仅使用 UIAlertAction.Style.whatever,它只能使其变为蓝色或红色。如果您更改 UIColor,它将使其成为您想要的任何颜色!

回答by ObiDan

There is a problem with setting the tint color on the view after presenting; even if you do it in the completion block of presentViewController:animated:completion:, it causes a flicker effect on the color of the button titles. This is sloppy, unprofessional and completely unacceptable.

呈现后在视图上设置色调颜色有问题;即使你在 presentViewController:animated:completion: 的完成块中这样做,它也会导致按钮标题颜色的闪烁效果。这是草率、不专业和完全不可接受的。

The one sure-fire way to solve this problem and to do it everywhere, is via adding a category to UIAlertController and swizzling the viewWillAppear.

解决这个问题并在任何地方都做的一个可靠的方法是通过向 UIAlertController 添加一个类别并调整 viewWillAppear。

The header:

标题:

//
//  UIAlertController+iOS9TintFix.h
//
//  Created by Flor, Daniel J on 11/2/15.
//

#import <UIKit/UIKit.h>

@interface UIAlertController (iOS9TintFix)

+ (void)tintFix;

- (void)swizzledViewWillAppear:(BOOL)animated;

@end

The implementation:

实施:

//
//  UIAlertController+iOS9TintFix.m
//
//  Created by Flor, Daniel J on 11/2/15.
//

#import "UIAlertController+iOS9TintFix.h"
#import <objc/runtime.h>

@implementation UIAlertController (iOS9TintFix)

+ (void)tintFix {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method method  = class_getInstanceMethod(self, @selector(viewWillAppear:));
        Method swizzle = class_getInstanceMethod(self, @selector(swizzledViewWillAppear:));
        method_exchangeImplementations(method, swizzle);});
}

- (void)swizzledViewWillAppear:(BOOL)animated {
    [self swizzledViewWillAppear:animated];
    for (UIView *view in self.view.subviews) {
        if (view.tintColor == self.view.tintColor) {
            //only do those that match the main view, so we don't strip the red-tint from destructive buttons.
            self.view.tintColor = [UIColor colorWithRed:0.0 green:122.0/255.0 blue:1.0 alpha:1.0];
            [view setNeedsDisplay];
        }
    }
}

@end

Add a .pch (precompiled header) to your project and include the category:

将 .pch(预编译头文件)添加到您的项目并包含类别:

#import "UIAlertController+iOS9TintFix.h"

Make sure you register your pch in the project properly, and it will include the category methods in every class that uses the UIAlertController.

确保您在项目中正确注册了您的 pch,它将在每个使用 UIAlertController 的类中包含类别方法。

Then, in your app delegates didFinishLaunchingWithOptions method, import your category and call

然后,在您的应用程序委托 didFinishLaunchingWithOptions 方法中,导入您的类别并调用

[UIAlertController tintFix];

and it will automatically propagate to every single instance of UIAlertController within your app, whether launched by your code or anyone else's.

并且它会自动传播到您应用程序中的每个 UIAlertController 实例,无论是由您的代码还是其他任何人的代码启动。

This solution works for both iOS 8.X and iOS 9.X and lacks the flicker of the tint change post-presentation approach.

此解决方案适用于 iOS 8.X 和 iOS 9.X,并且没有呈现后色调更改方法的闪烁。

Mad props to Brandon above for starting this journey, unfortunately my reputation was not sufficient enough to comment on his post, or else I would have left it there!

疯狂的支持布兰登开始这次旅程,不幸的是我的声誉不足以评论他的帖子,否则我会把它留在那里!

回答by lin

[[UIView appearance] setTintColor:[UIColor black]];  

this will change all the UIView tintColoras well as UIAlertController's view

这将改变所有UIView tintColor以及UIAlertController的观点

回答by Dheeraj D

You can change it using: Swift 3.x

您可以使用以下方法更改它:Swift 3.x

    strongController.view.tintColor = UIColor.green

回答by Brandon Schlenker

I found a solution to this. Not an elegant solution, but a solution.

我找到了解决方案。不是一个优雅的解决方案,而是一个解决方案。

I swizzled viewWillAppear: on UIAlertController, then looped through the views and modified the tint color. In my case I had a tintColor set on the entire window and despite setting the tintColor via appearance the UIAlertController maintained the color on the window. I check if the color is equal to that of the window and if so apply a new one. Blindly applying the tintColor to all views will result in the red tint on destructive actions to be reset.

我 swizzled viewWillAppear: 在 UIAlertController 上,然后循环浏览视图并修改色调颜色。就我而言,我在整个窗口上设置了 tintColor,尽管通过外观设置了 tintColor,但 UIAlertController 仍保持窗口上的颜色。我检查颜色是否等于窗口的颜色,如果是,则应用新的颜色。盲目地将 tintColor 应用于所有视图将导致破坏性操作的红色色调被重置。

+ (void)load  
{  
    static dispatch_once_t onceToken;  
    dispatch_once(&onceToken, ^{  
        Method swizzleMethod = class_getInstanceMethod(self, @selector(viewWillAppear:));  
        Method method = class_getInstanceMethod(self, @selector(alertSwizzle_viewWillAppear:));  
        method_exchangeImplementations(method, swizzleMethod);  
    });  
}  

- (void)alertSwizzle_viewWillAppear:(BOOL)animated  
{  
    [self alertSwizzle_viewWillAppear:animated];  
    [self applyTintToView:self.view];  
}  

- (void)applyTintToView:(UIView *)view  
{  
    UIWindow *mainWindow = [UIApplication sharedApplication].keyWindow;  

    for (UIView *v in view.subviews) {  
        if ([v.tintColor isEqual:mainWindow.tintColor]) {  
            v.tintColor = [UIColor greenColor];  
        }  
        [self applyTintToView:v];  
    }  
}  

However this doesn't work on iOS 8, so you'll still need to set the apperance tint color.

但是,这在 iOS 8 上不起作用,因此您仍然需要设置外观色调颜色。

[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor greenColor]];