yohunl's iOS blog

时间顺流而下,生活逆水行舟

用来记录平时的一些心得!


谈谈改变 UIAlertView 和 UIActionSheet 的颜色

iOS8及以上应该使用的方式

对于>=iOS8来说, UIAlertView,UIActionSheet都被 UIAlertController替代了, 建立一个 UIAlertView的方式

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title"  
                                                                                 message:@"Message"
                                                                          preferredStyle:UIAlertControllerStyleAlert];
建立一个UIActionSheet
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title"
                                                                                 message:@"Message"
                                                                          preferredStyle:UIAlertControllerStyleActionSheet];

改变 UIAlertController 颜色的方式

        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title"
                                                                                 message:@"Message"
                                                                          preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *cancelButton = [UIAlertAction actionWithTitle:@"Cancel"
                                                               style:UIAlertActionStyleCancel
                                                             handler:nil];
        UIAlertAction *destructiveButton = [UIAlertAction actionWithTitle:@"Destructive"
                                                                    style:UIAlertActionStyleDestructive
                                                                  handler:nil];
        UIAlertAction *otherButton1 = [UIAlertAction actionWithTitle:@"Button 1"
                                                               style:UIAlertActionStyleDefault
                                                             handler:nil];
        UIAlertAction *otherButton2 = [UIAlertAction actionWithTitle:@"Button 2"
                                                               style:UIAlertActionStyleDefault
                                                             handler:nil];
        [alertController addAction:cancelButton];
        [alertController addAction:destructiveButton];
        [alertController addAction:otherButton1];
        [alertController addAction:otherButton2];
        alertController.view.tintColor = [UIColor colorWithRed:0.7596 green:0.5249 blue:1.0 alpha:1.0];//这句就可以了! 当然了,如果你没设置这一句,
        [self presentViewController:alertController animated:YES completion:nil];

UIAlertViewpic1.png 总结出来的可以用来改变颜色的方式

方法1: 修改alertController.view.tintColor的tintColor

alertController.view.tintColor = [UIColor colorWithRed:0.7596 green:0.5249 blue:1.0 alpha:1.0];  

但是,实际上,在测试的时候,发现,这种修改后,手指在选项上滑动后,颜色就又变为默认的蓝色了.......,具体可以看下面的gif动画演示 UIAlertViewpic2.gif

另外 stackoverflow上很多说是在AppDelegate中添加

[[UIView appearanceWhenContainedInInstancesOfClasses:@[[UIAlertController class]]] setTintColor:[UIColor redColor]];

可以让所有的UIAlertController的颜色都改变,但是,但是,经过我测试,添加这句根本没有效果,不仅没有效果,添加了这句后,这样的设置alertController.view.tintColor = [UIColor colorWithRed:0.7596 green:0.5249 blue:1.0 alpha:1.0];将不再有效,系统弹出的是默认的颜色了!!!! 至于为什么会这样,我也没有得到一个可以让自己信服的理由!

方法2: 修改window的tintColor,这种方式不会有方式一的问题

[UIApplication sharedApplication].keyWindow.tintColor = [UIColor yellowColor];

至于这句在什么地方加,当然是随你心情了,只要在其显示之前添加,都是OK的

方法3: 私有API(注意这种方式不能上appstore的,会因为调用私有api被苹果拒的) 从iOS-Runtime-Headers中UIAlertAction头文件我们可以看到 UIAlertAction 有一个私有api

- (void)_setTitleTextColor:(id)arg1;

从名字就可以看出,这个是改变文字颜色的

在代码中

        UIAlertAction *otherButton1 = [UIAlertAction actionWithTitle:@"Button 1"
                                                               style:UIAlertActionStyleDefault
                                                             handler:nil];
        [otherButton1 performSelector:@selector(_setTitleTextColor:) withObject:[UIColor yellowColor]];

就可以实现了!

方法4 : 使用KVC

  [otherButton1 setValue:[UIColor yellowColor] forKey:@"titleTextColor"];
  //[otherButton1 setValue:[UIColor yellowColor] forKey:@"_titleTextColor"];

这种方式,是合法的方式调用私有方法或者属性,这个是KVC的特性决定的

使用以前的UIAlertView的怎么改变呢?

网上的第一种方式

使用Appearance的方式 ios9之前

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

ios9之后

    [[UIView appearanceWhenContainedInInstancesOfClasses:@[[UIAlertView class]]] setTintColor:[UIColor redColor]];
    [[UIView appearanceWhenContainedInInstancesOfClasses:@[[UIAlertController class]]] setTintColor:[UIColor redColor]];

经过测试,是起不到任何作用的,因为苹果官方上说到了 Appearance of Alert Views You cannot customize the appearance of alert views.

网上的第二种方式:重载UIAlertView

可以参考[how-to-change-color-of-the-uialertview-dialog-in-ios]( http://stackoverflow.com/questions/9940145/how-to-change-color-of-the-uialertview-dialog-in-ios)

但是这个有一个问题,UIAlertView内部的实现,在不同版本是不一样的,所以即使在一个sdk上可以了,其它的也不一定可以,尤其是在iOS9中, 我们从iOS-Runtime-Headers查看UIAlertView的头文件

@interface UIAlertView : UIView {
    BOOL __currentlyRunningModal;
    NSMutableArray *_actions;
    UIAlertController *_alertController;
    BOOL _alertControllerShouldDismiss;
    int _alertViewStyle;
    int _cancelIndex;
    id _context;
    int _defaultButtonIndex;
    id _delegate;
    BOOL _dismissingAlertController;
    UIViewController *_externalViewControllerForPresentation;
    int _firstOtherButtonIndex;
    BOOL _handlingAlertActionShouldDismiss;
    BOOL _hasPreparedAlertActions;
    BOOL _isPresented;
    NSString *_message;
    _UIAlertControllerShimPresenter *_presenter;
    UIAlertView *_retainedSelf;
    BOOL _runsModal;
    NSString *_subtitle;
}

可以看到,其内部实现可能已经换为 VIewController的形式来实现了!!

所以这种方式也不行的!!

网上的第三种方式

[how-to-change-uialertview-text-color]( http://stackoverflow.com/questions/4755313/how-to-change-uialertview-text-color),枚举UIAlertView的子视图,然后更改

-(void)willPresentAlertView:(UIAlertView *)alertView
{
    UILabel *titleLabel = [alertView valueForKey:@"_titleLabel"];
    titleLabel.font = [UIFont fontWithName:@"Arial" size:18];
    [titleLabel setTextColor:[UIColor whiteColor]];

     UILabel *body = [alertView valueForKey:@"_bodyTextLabel"];
     body.font = [UIFont fontWithName:@"Arial" size:15];
     [body setTextColor:[UIColor whiteColor]];

}

但是,这个是不行的!!!在iOS9中,内部实现已经改变,根本没有_titleLabel ,如果你这样写,直接就crash了

那么,难道没有方法改变UIAlertView的颜色了么??? 有啊,完全的使用自定义的AlertView.

第四种方式,也是唯一可行的方式

完全使用自定义的AlertView,这样,什么颜色更改呀,字体更改呀,都没有问题了!! 可以参考 https://github.com/Friend-LGA/LGAlertView

https://github.com/szk-atmosphere/MSAlertController

UIActionSheet的颜色改变

同上述的UIAlertView的方式!

参考 uialertcontroller-custom-font-size-color有讨论

最近的文章

iOS 越狱的Tweak开发

iOS 越狱的Tweak开发 iOS越狱开发中,各种破解补丁的统称为Tweak,通常意义上我们说的越狱开发,都是指开发一个Tweak. 基本上,tweak都依赖于一个名叫cydia Subst…

继续阅读
更早的文章

respondsToSelector和 instancesRespondToSelector的理解

respondsToSelector 和 instancesRespondToSelector是两个常用的方法,我们经常使用 someObject respondsToSelector,但是对于…

继续阅读