36

In my project, I am using UIActionSheet for displaying for some sorting type. I want to change the color of the text displayed in the action sheet buttons. How can we change the text color?

Arnaud
  • 6,339
  • 8
  • 47
  • 64
kiri
  • 1,907
  • 5
  • 26
  • 51

11 Answers11

76

iOS 8: UIActionSheet is deprecated. UIAlertController respects -[UIView tintColor], so this works:

alertController.view.tintColor = [UIColor redColor];

Better yet, set the whole window's tint color in your application delegate:

self.window.tintColor = [UIColor redColor];

iOS 7: In your action sheet delegate, implement -willPresentActionSheet: as follows:

- (void)willPresentActionSheet:(UIActionSheet *)actionSheet
{
    for (UIView *subview in actionSheet.subviews) {
        if ([subview isKindOfClass:[UIButton class]]) {
            UIButton *button = (UIButton *)subview;
            [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        }
    }
}
jrc
  • 15,615
  • 8
  • 60
  • 56
  • 3
    This works only default state. If you tap the button, it keep blue color on the titleLabel. – seufagner Nov 01 '13 at 18:17
  • 3
    Thanks. Try [button setTitleColor:fooColor forState:UIControlStateNormal] instead. – jrc Nov 07 '13 at 16:25
  • This just doesn't work at all on the iPhone simulator. – Reuben Scratton Jan 07 '14 at 13:13
  • Reuben - Not sure what you're doing wrong but it works fine in Simulator. – wuf810 Jun 21 '14 at 06:55
  • 1
    People, stop iterating through Apple's private controls subviews. This is bad, will crash one day and will make other developers laugh at you. – msmialko Feb 16 '15 at 17:32
  • @msmialko it's only private if it's not public. But it doesn't make it wrong, especially if Apple approves them. It's a shame Apple has to restrict access to simple fundamental features like the colors of a string just so we have to go and create our own from scratch. Have you ever tried to change the title color of the cancel button in a UISearchBar? I guess Apple thinks everyone sees only blue – soulshined Feb 25 '15 at 07:39
  • This is a guidelines violation, while setting your custom color to the destructive buttons (if one is presented in your sheet), which must be red. – kas-kad Mar 02 '15 at 11:49
  • 1
    You are using something you assume Apple won't change, which is not the case in iOS 8, the code is not safe – Boda Mar 08 '15 at 15:43
  • 2
    Guys, this isn't using a private API; -[UIView subviews] is very much public. But changing text color this way is of course not what Apple intended, so you could say it is private "in spirit". If your designer or product owner asks for this to be done, here is a way. If you don't think it should be done, don't do it. End of story. – jrc Mar 09 '15 at 12:18
  • 1
    Yes it's not using private API but you are assuming the subviews inside the action sheet will remain UIButtons which is not valid, they might change by Apple cause they are not documented and not provided through public API – Boda Mar 10 '15 at 11:33
  • @msmialko iterating using strong condition dont crash anything. I've olds app with ios 6 sdk actually running in ios9 devices..what do you understand is what do you doing.. – Alessandro Ornano May 07 '16 at 11:27
20

In iOS 8, none of this works anymore. UIActionSheet text seems to get its color from window.tintColor.

lifjoy
  • 2,099
  • 21
  • 19
  • Sorry for the late reply. My workaround was to stop changing window.tintColor or self.view.tintColor to white. Instead, I'm now explicitly setting any elements which need a white tintColor, rather than relying upon parent view tintColors. – lifjoy Sep 22 '14 at 20:37
  • Nice post! I was wondering all the time why my `UIAlertViews` and `UIAlertController`appear in `whiteColor`. – Alex Cio Nov 13 '14 at 13:20
  • 5
    In iOS8, UIActionSheet is deprecated. You can use UIAlertController and set tintColor on the alert controller view. – Brody Robertson Nov 17 '14 at 22:38
17

This works for me in iOS8

[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor redColor]];
blacksheep_2011
  • 863
  • 2
  • 9
  • 19
  • 4
    This will change the color of all the buttons, including the cancel button. Is there a way to change the color to red, but not for the cancel button? – etayluz Mar 16 '15 at 05:20
12

If ever you want to go through the UIActionSheet's subviews, you should not directly set the text color of the UILabel but use the UIButton setTitleColor:forState method instead. Otherwise, the initial color will be set back upon events like UIControlEventTouchDragOutside for example.

Here is the proper way to do it, reusing the jrc's code:

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

May be a late answer but I figure it could help someone.

iOS 8: You could simply initialize your UIAlertAction with the style: UIAlertActionStyleDestructive like so:

UIAlertAction *delete = [UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action){

   // your code in here   

}];

This will make the button's text red by default.

enter image description here

Julius
  • 837
  • 1
  • 8
  • 19
6

To change particular buttons colour in alert action use this

let cancelAction = UIAlertAction(title: "Success", style: .cancel, handler: nil)
cancelAction.setValue(UIColor.green, forKey: "titleTextColor")

Asif
  • 219
  • 3
  • 5
2

@jrc solution works, but titleLabel color changes when you tap the button. Try this to keep the same color at all states.

- (void)willPresentActionSheet:(UIActionSheet *)actionSheet
{     
 UIColor *customTitleColor = [UIColor greenColor];
      for (UIView *subview in actionSheet.subviews) {
        if ([subview isKindOfClass:[UIButton class]]) {
          UIButton *button = (UIButton *)subview;

          [button setTitleColor:customTitleColor forState:UIControlStateHighlighted];
          [button setTitleColor:customTitleColor forState:UIControlStateNormal];
          [button setTitleColor:customTitleColor forState:UIControlStateSelected];
        }
      }
}
seufagner
  • 1,130
  • 1
  • 16
  • 24
2

Soulution for Swift 3. Changes all colors.

UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .yellow
kubacizek
  • 470
  • 4
  • 9
1

EDIT

Here is a similar question: How to customize Buttons in UIActionSheet?

Try to use the appearance protocol [NOT WORKING]

 UIButton *btn = [UIButton appearanceWhenContainedIn:[UIActionSheet class], nil];
 [btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
Community
  • 1
  • 1
alexcristea
  • 2,130
  • 14
  • 18
1

use this for ios 8 and above

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.
}
Ravish
  • 17
  • 2
0

UIAppearance can handle this:

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

Much easier than going through the subviews, but I haven't tested this solution on iOS 6 or earlier.

cantoni
  • 11