Change Text Color of Items in UIActionSheet - iOS 8

43,705

Solution 1

There's an easy way if you still want to use UIActionSheet instead of UIAlertController in order to support older iOS versions.

UIActionSheet actually uses UIAlertController in iOS 8, and it has a private property _alertController.

SEL selector = NSSelectorFromString(@"_alertController");
if ([actionSheet respondsToSelector:selector])
{
    UIAlertController *alertController = [actionSheet valueForKey:@"_alertController"];
    if ([alertController isKindOfClass:[UIAlertController class]])
    {
        alertController.view.tintColor = [UIColor blueColor];
    }
}
else
{
    // use other methods for iOS 7 or older.
}

For Swift Below code should works

let alertAction = UIAlertAction(title: "XXX", style: .default) { (action) in

     }

    alertAction.setValue(UIColor.red, forKey: "titleTextColor")

Solution 2

To change the button title color you need to use UIAlertController and set the tintColor of the main view.

Example of setting the button title colors to black:

UIAlertController *actionSheetController = [UIAlertController alertControllerWithTitle:@"How would you like to proceed?" message:@"" preferredStyle:UIAlertControllerStyleActionSheet];

UIAlertAction *finish = [UIAlertAction actionWithTitle:@"Finish" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action)
                               {
                                   [self performSelector:@selector(finish:) withObject:nil];
                               }];

UIAlertAction *playAgain = [UIAlertAction actionWithTitle:@"Play Again" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action)
                            {
                                [self performSelector:@selector(playAgain:) withObject:nil];
                            }];

UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action)
                         {
                             [actionSheetController dismissViewControllerAnimated:YES completion:nil];
                         }];

[actionSheetController addAction:finish];
[actionSheetController addAction:playAgain];
[actionSheetController addAction:cancel];

//******** THIS IS THE IMPORTANT PART!!!  ***********
actionSheetController.view.tintColor = [UIColor blackColor];

[self presentViewController:actionSheetController animated:YES completion:nil];

Solution 3

Ok, I ran into the same problem but I think I have found a solution:

The appropriate way should be like this and I guess it works in iOS7:

[[UIButton appearanceWhenContainedIn:[UIActionSheet class], nil] setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];

But it will not work in iOS8 due to the fact that the ActionSheets "buttons" is now based on a UICollectionView. So after some digging around I got this to work instead:

[[UICollectionView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor blueColor]];

Solution 4

I'm using it.

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

Add one line (AppDelegate) and works for all UIAlertController.

Solution 5

I have same task and I've made this hack today, dirty, but it works

class CustomAlertViewController: UIAlertController {

    internal var cancelText: String?


    private var font: UIFont? = UIFont(name: "MuseoSansCyrl-500", size: 12)

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.tintColor = UIColor.blackColor()
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

        self.findLabel(self.view) //if you need ios 9 only, this can be made in viewWillAppear
    }

    func findLabel(scanView: UIView!) {
        if (scanView.subviews.count > 0) {
            for subview in scanView.subviews {
                if let label: UILabel = subview as? UILabel {

                    if (self.cancelText != nil && label.text == self.cancelText!) {
                        dispatch_async(dispatch_get_main_queue(),{
                            label.textColor = UIColor.redColor() //for ios 8.x
                            label.tintColor = UIColor.redColor() //for ios 9.x
                        })
                    }

                    if (self.font != nil) {
                        label.font = self.font
                    }
                }

                self.findLabel(subview)
            }
        }
    }

}
Share:
43,705
Salman Zaidi
Author by

Salman Zaidi

Updated on July 09, 2022

Comments

  • Salman Zaidi
    Salman Zaidi almost 2 years

    I had been using following code to change text color of items which I add in UIActionSheet.:

    - (void)willPresentActionSheet:(UIActionSheet *)actionSheet {
        for (UIView *subview in actionSheet.subviews) {
            if ([subview isKindOfClass:[UIButton class]]) {
                UIButton *button = (UIButton *)subview;
                [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            }
        }
    }
    

    It works fine in iOS7, but in iOS8 the above code doesn't change the text color of items.

    Now my question is how to change the text color of items which I add in UIActionSheet using iOS8??

    Additional Info:
    I added breakpoint to see whether following lines from the above code get executed or not:

    UIButton *button = (UIButton *)subview;
    [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    

    These lines do not get executed. So, if([subview isKindOfClass:[UIButton class]]) is always false for all items of actionSheet.subviews. So what I think is that the view heirarchy of UIActionSheet has been changed.

  • Jorge
    Jorge almost 10 years
    This is a great answer. Although, I'm still looking for a way to set each button tint as well as the backgroundColor of the UIAlertController. Any thoughts?
  • DiscDev
    DiscDev almost 10 years
    @Jorge I remember reading somewhere that Apple doesn't want you to customize action sheet / alert colors. I believe that if you want to do more customizations than what I mentioned you'd need to make your own alert class, or borrow one of the many readily available open source options from github.
  • Jorge
    Jorge almost 10 years
    Yes, that's what I thought. Actually, I do use UIView with buttons for this purpose sometimes, but it would be a lot easier to just customize UIAlertController. Thanks a lot. @DiscDev
  • Mundi
    Mundi almost 10 years
    This is not working with style .Alert. Most likely Apple does not foresee the modification of alerts.
  • Teffi
    Teffi almost 10 years
    Can we at least change the font and title color? Apple should atleast allowed us to do simple customization rather than using uiview that would function like an alertview or actionsheet.
  • Tim
    Tim almost 10 years
    Yes, part of the purpose of GUI (graphical) is to make it clear and obvious sometimes by color, such as when one is about to Delete something, the color red is used to indicate, you are about to do something with potential consequences. Some of apples choices since Steve Job's passing do not seem wise.
  • DiscDev
    DiscDev almost 10 years
    @Tim the iOS SDK has never allowed you to customize action sheets or alerts colors from version 1. Doesn't have anything to do with the late Mr. Jobs. They want a consistent experience. If you want something more flexible, you'll have to make it yourself.
  • Whoami
    Whoami over 9 years
    DiscDev, thanks, is it possible to change the individual UIAlertAction button different color?
  • DiscDev
    DiscDev over 9 years
    @Whoami doubtful. Apple doesn't want you to customize alerts/actionsheets. They suggest you make your own if you want a custom look and feel. There are lots of projects on github for this, go have a look there.
  • huong
    huong over 9 years
    Am I the only sees that this changes color for all buttons except for Cancel button?
  • DiscDev
    DiscDev over 9 years
    This will definitely have unintended side effects and is not advised. Changing the tint color for all UICollectionViews inside UIAlertController is fragile and relies on the view hierarchy Apple has chosen for the current version of iOS. As you can see from this answer, they changed the view hierarchy from iOS 7-> iOS 8, what's to keep them from doing it again in iOS 9? This will surely require updating in the future and is not advised.
  • André Fratelli
    André Fratelli over 9 years
    Using private properties will probably get the app rejected
  • Saren Inden
    Saren Inden over 9 years
    To do this correct you should use UIActionSheet and UIAlertView on iOS7 and below and UIAlertController on iOS8 and above. For my projects I wrote a 'custom' AlertController that automatically picks the right method based on the OS version. To bad I cannot share but I would definitely recommend doing this also because there are some bugs that might occur on iOS8 when using UIActionSheet
  • matzino
    matzino over 9 years
    Setting the tintColor works well, but the gap between Default- and Cancel-Style-Items is than missing :(
  • Benjohn
    Benjohn over 9 years
    Best solution imo. I added a few tweaks for backwards compatibility and to get the default tint colour, which isn't UIColor.blueColor.
  • Benjohn
    Benjohn over 8 years
    This doesn't work for iPads on iOS 9, for some reason. Poo. :-(
  • whyoz
    whyoz over 8 years
    [self.window setTintColor:[UIColor whateverColor]] is the only thing I've found that works in iOS 8 and 9
  • Benjohn
    Benjohn over 8 years
    @whyoz I'll look at that – I've already set this to something else for some reason, but perhaps I can achieve that elsewhere…
  • mnl
    mnl over 8 years
    @friedegg-bacon-sandwich i'm getting everything in tint color except the cancel button as well. looks extremely stupid. do you know how to set the cancel button to tint color as well?
  • qqilihq
    qqilihq over 8 years
    While this does not answer OP's question, it just solved my specific issue. Thanks!
  • BFeher
    BFeher over 8 years
    @friedegg-bacon-sandwich Did anybody ever solve the stubborn cancel button issue?
  • Syed Ali Salman
    Syed Ali Salman about 8 years
    Will this be rejected by apple? If I use this?
  • AbdulMomen عبدالمؤمن
    AbdulMomen عبدالمؤمن about 8 years
    this answer is the best.
  • Pauls
    Pauls almost 8 years
    I had to set actionSheetController.view.tintColor = [UIColor blackColor]; again in the completion block to have not flicker the color after tapping on the buttons!
  • Tung Vu Duc
    Tung Vu Duc almost 6 years
    Great, but how do you know that pro ?
  • infiniteLoop
    infiniteLoop over 2 years
    This has been answered above already. Also it will be rejected as already pointed out.