如何更改 iOS9 中的 UIAlertController 按钮文本颜色?
How to change UIAlertController button text colour in iOS9?
问题类似于iOS 8 UIActivityViewController and UIAlertController button text color uses window's tintColor,但在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];
我在过去 运行 遇到过类似的事情,问题似乎源于警报控制器的视图在显示之前尚未准备好接受 tintColor
更改。或者,尝试设置色调颜色 AFTER 你展示你的警报控制器:
[self presentViewController:strongController animated:YES completion:nil];
strongController.view.tintColor = [UIColor black];
我找到了解决方法。不是一个优雅的解决方案,而是一个解决方案。
我在 UIAlertController 上调换了 viewWillAppear:,然后遍历视图并修改了色调。在我的例子中,我在整个 window 上设置了 tintColor,尽管通过外观设置了 tintColor,但 UIAlertController 保持了 window 上的颜色。我检查颜色是否与 window 的颜色相同,如果是,则应用一个新颜色。盲目地将 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]];
我可以通过继承 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
呈现后在视图上设置色调颜色时出现问题;即使您在 presentViewController:animated:completion: 的完成块中执行此操作,它也会对按钮标题的颜色造成闪烁效果。这是草率的,不专业的,完全不能接受的。
解决这个问题并在任何地方都这样做的 sure-fire 方法是通过向 UIAlertController 添加一个类别并调整 viewWillAppear。
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
实施:
//
// 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(预编译 header)添加到您的项目并包含类别:
#import "UIAlertController+iOS9TintFix.h"
确保您在项目中正确注册了您的 pch,它将在每个使用 UIAlertController 的 class 中包含类别方法。
然后,在您的应用委托 didFinishLaunchingWithOptions 方法中,导入您的类别并调用
[UIAlertController tintFix];
并且它会自动传播到您应用中的每个 UIAlertController 实例,无论是由您的代码还是其他任何人启动的。
此解决方案适用于 iOS 8.X 和 iOS 9.X,并且缺少色调变化 post-presentation 方法的闪烁。
疯狂支持布兰登开始这段旅程,不幸的是我的声誉不足以评论他的post,否则我会把它留在那里!
[[UIView appearance] setTintColor:[UIColor black]];
这将改变所有 UIView tintColor
以及 UIAlertController
的观点
Objective-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)
在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)
您可以使用以下方式更改它:Swift 3.x
strongController.view.tintColor = UIColor.green
在Swift 3.x:
我发现以下方法很有效。我在应用程序启动时调用它。
UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = UIColor.black
所以这会全局更改您应用中所有 UIAlertViewController 按钮标签的色调。唯一不会改变的按钮标签颜色是具有破坏性 UIAlertActionStyle 的按钮标签颜色。
您有 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()
}))
我想让删除按钮显示为红色,所以我使用了.destructive 样式:
alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler:{(UIAlertAction) in
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
}
}
最合理的方法是设置主要window的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 和覆盖布局方法是 hack 方式,这是不可接受的。
经过大量研究,我发现了如何使这项工作有效:
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 来制作它。):
只用UIAlertAction.Style.whatever,只能做成蓝色或红色。如果你改变 UIColor,它会变成你想要的任何颜色!
问题类似于iOS 8 UIActivityViewController and UIAlertController button text color uses window's tintColor,但在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];
我在过去 运行 遇到过类似的事情,问题似乎源于警报控制器的视图在显示之前尚未准备好接受 tintColor
更改。或者,尝试设置色调颜色 AFTER 你展示你的警报控制器:
[self presentViewController:strongController animated:YES completion:nil];
strongController.view.tintColor = [UIColor black];
我找到了解决方法。不是一个优雅的解决方案,而是一个解决方案。
我在 UIAlertController 上调换了 viewWillAppear:,然后遍历视图并修改了色调。在我的例子中,我在整个 window 上设置了 tintColor,尽管通过外观设置了 tintColor,但 UIAlertController 保持了 window 上的颜色。我检查颜色是否与 window 的颜色相同,如果是,则应用一个新颜色。盲目地将 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]];
我可以通过继承 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
呈现后在视图上设置色调颜色时出现问题;即使您在 presentViewController:animated:completion: 的完成块中执行此操作,它也会对按钮标题的颜色造成闪烁效果。这是草率的,不专业的,完全不能接受的。
解决这个问题并在任何地方都这样做的 sure-fire 方法是通过向 UIAlertController 添加一个类别并调整 viewWillAppear。
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
实施:
//
// 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(预编译 header)添加到您的项目并包含类别:
#import "UIAlertController+iOS9TintFix.h"
确保您在项目中正确注册了您的 pch,它将在每个使用 UIAlertController 的 class 中包含类别方法。
然后,在您的应用委托 didFinishLaunchingWithOptions 方法中,导入您的类别并调用
[UIAlertController tintFix];
并且它会自动传播到您应用中的每个 UIAlertController 实例,无论是由您的代码还是其他任何人启动的。
此解决方案适用于 iOS 8.X 和 iOS 9.X,并且缺少色调变化 post-presentation 方法的闪烁。
疯狂支持布兰登开始这段旅程,不幸的是我的声誉不足以评论他的post,否则我会把它留在那里!
[[UIView appearance] setTintColor:[UIColor black]];
这将改变所有 UIView tintColor
以及 UIAlertController
的观点
Objective-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)
在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)
您可以使用以下方式更改它:Swift 3.x
strongController.view.tintColor = UIColor.green
在Swift 3.x:
我发现以下方法很有效。我在应用程序启动时调用它。
UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = UIColor.black
所以这会全局更改您应用中所有 UIAlertViewController 按钮标签的色调。唯一不会改变的按钮标签颜色是具有破坏性 UIAlertActionStyle 的按钮标签颜色。
您有 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()
}))
我想让删除按钮显示为红色,所以我使用了.destructive 样式:
alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler:{(UIAlertAction) in
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
}
}
最合理的方法是设置主要window的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 和覆盖布局方法是 hack 方式,这是不可接受的。
经过大量研究,我发现了如何使这项工作有效:
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 来制作它。):
只用UIAlertAction.Style.whatever,只能做成蓝色或红色。如果你改变 UIColor,它会变成你想要的任何颜色!