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

时间:2015-09-30 02:44:53

标签: ios objective-c uialertcontroller

问题类似于enter image description here,但在iOS 9中。

我有一个UIAlertController,即使我试图设置

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

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

14 个答案:

答案 0 :(得分:56)

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

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

答案 1 :(得分:14)

在Swift 3.x中:

我发现以下内容可以有效地发挥作用。我在应用程序启动时调用它。

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

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

答案 2 :(得分:12)

我能够通过继承UIAlertController

来解决这个问题
class MyUIAlertController: UIAlertController {

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

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

当警报显示时,设备旋转幸免于难。

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

虽然在iOS 8.4上没有必要,但此代码也适用于iOS 8.4。

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

答案 3 :(得分:12)

<强> 目标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

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)

答案 4 :(得分:4)

在呈现后在视图上设置色调颜色存在问题;即使你在presentViewController:animated:completion:的完成块中执行它,它也会对按钮标题的颜色产生闪烁效果。这是草率的,不专业的,完全不可接受的。

通过向UIAlertController添加一个类别并调整viewWillAppear来解决此问题并在任何地方实现这一目标的一种确定方法。

标题:

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

实施:

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

将.pch(预编译头)添加到项目中并包含以下类别:

#import "UIAlertController+iOS9TintFix.h"

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

然后,在你的app中委托didFinishLaunchingWithOptions方法,导入你的类别并调用

[UIAlertController tintFix];

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

此解决方案适用于iOS 8.X和iOS 9.X,并且缺少色彩更改后呈现方式的闪烁。

上面开始这段旅程的疯狂道具给Brandon,不幸的是我的声誉不足以评论他的帖子,否则我会把它留在那里!

答案 5 :(得分:4)

<强> swift3

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

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

extension UIAlertController {

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

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

答案 6 :(得分:3)

> mkdir ~/host
> docker run -d -v ~/host:/vol-mounted -v /vol-not-mounted busybox
89783d441a74a3194ce9b0d57fa632408af0c5981474ec500fb109a766d05370
> docker inspect --format '{{json .Mounts}}' 89
[{
    "Source": "/home/scrapbook/host",
    "Destination": "/vol-mounted",
    "Mode": "",
    "RW": true,
    "Propagation": "rprivate"
}, {
    "Name": "55e2f1dd9e490f1e3ce53a859075a20462aa540cd72fac7b4fbe6cd26e337644",
    "Source": "/var/lib/docker/volumes/55e2f1dd9e490f1e3ce53a859075a20462aa540cd72fac7b4fbe6cd26e337644/_data",
    "Destination": "/vol-not-mounted",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
}]

这将更改所有[[UIView appearance] setTintColor:[UIColor black]]; 以及UIView tintColor的视图

答案 7 :(得分:2)

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

我在UIAlertController上调整了viewWillAppear:然后循环浏览视图并修改了色调颜色。在我的情况下,我在整个窗口上设置了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];  
    }  
}  

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

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

答案 8 :(得分:2)

您可以使用以下方式进行更改: Swift 3.x

using System;

答案 9 :(得分:1)

在Swift 2.2中,您可以使用以下代码

 // LogOut or Cancel
    let logOutActionSheet: UIAlertController = UIAlertController(title: "Hello Mohsin!", message: "Are you sure you want to logout?", preferredStyle: .Alert)

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

    let cancelActionButton: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
        print("Cancel Tapped")
    }

    logOutActionSheet.addAction(cancelActionButton)

    let logOutActionButton: UIAlertAction = UIAlertAction(title: "Clear All", style: .Default)
    { action -> Void in
        //Clear All Method
        print("Logout Tapped")

    }

    logOutActionButton.setValue(UIColor.redColor(), forKey: "titleTextColor")

    logOutActionSheet.addAction(logOutActionButton)

答案 10 :(得分:0)

操作按钮有3种样式:

let style : UIAlertActionStyle = .default
// default, cancel (bold) or destructive (red)

let alertCtrl = UIAlertController(....)
alertCtrl.addAction( UIAlertAction(title: "click me", style: style, handler: {
    _ in doWhatever()
}))

答案 11 :(得分:0)

我想让删除按钮显示为红色,所以我使用了.destructive样式:

 alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler:{(UIAlertAction) in

答案 12 :(得分:0)

最合理的方法是设置主窗口的tintColor。因为统一的外观是我们通常需要的。

// in app delegate
window.tintColor = ...

其他解决方案存在缺陷

  • 使用外观

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

    不适用于iOS 9,使用iOS 11 SDK进行测试。

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

    你认真吗?

  • 设置UIAlertController视图的tintColor不稳定。当用户按下按钮或在视图布局之后,颜色可能会改变。

  • 子类UIAlertController和覆盖布局方法是黑客方式,这是不可接受的。

答案 13 :(得分:0)

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

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)

只需将UIColor.systemBlue更改为所需的颜色,它将使该按钮成为特殊颜色。我做了这个例子(我创建了3个UIAlertActions来实现):
enter image description here

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