Adding Images to UIActionSheet buttons as in UIDocumentInteractionController
Asked Answered
P

12

33

Is it possible to add an image to the buttons of the UIActionSheet as seen in UIDocumentInteractionController? If so, please let me know how it is done.

Propeller answered 25/5, 2011 at 20:28 Comment(1)
With UIActionSheet I don't believe you can actually access the buttons. Might be easier to create an action sheet like view that just uses standard UIButtons and animations.Marquise
P
27

Try this way, i hope it may be help you.

UIActionSheet * action = [[UIActionSheet alloc] 
                      initWithTitle:@"Title" 
                      delegate:self 
                      cancelButtonTitle:@"Cancel" 
                      destructiveButtonTitle:nil 
                      otherButtonTitles:@"",nil];

[[[action valueForKey:@"_buttons"] objectAtIndex:0] setImage:[UIImage imageNamed:@"yourImage.png"] forState:UIControlStateNormal];

[[[action valueForKey:@"_buttons"] objectAtIndex:0] setImage:[UIImage imageNamed:@"yourImage_Highlighted.png"] forState:UIControlStateHighlighted];
Provincialism answered 26/5, 2011 at 10:19 Comment(6)
are you positive that this method is legal and i can post my app to the App Store?Propeller
I have same question ? Did submitted to app store with this code ?Papillote
So, will this get rejected or not?Wilmott
Apple considers accessing non-publicly-documented portions of their view hierarchies to be "private API"; this approach risks App Store rejection.Farflung
I have an app with this submitted.Digastric
i have same problem.. my app is crashed in iOS8Showman
Q
71

There is a possibility to add images (to be exact: icons or symbols) to the buttons of a UIActionSheet (or a UIAlertView) without loading image files or fiddling around with (sub)views. In these classes buttons are specified by their titles, which are strings. So it is obvious to use symbols, which one can specify also by strings. The first I came up with was using unicode symbols.

Then I discovered that several of them are rendered as nice icons on iOS and as one can see for several symbols in the Character Viewer on Mac OS, too. Thus, the symbols can be used actually everywhere a string can be specified.

The drawbacks of this approach are:

  • You are limited to predefined symbols.
  • Not all symbols are rendered as they should (e.g. \u29C9).
  • There can be changes in the appearance of some symbols on different iOS versions (e.g. \U0001F533 on iOS 5 and 6).

Here are some interesting symbols among others:

If you want to quickly check how a symbol looks like (at least on Mac OS), you can use the Calculator. Check definitely in the simulator: For instance \u2B1C is not an icon in Calculator 10.7.1.

Screenshots:

UIActionSheet

UIActionSheet

Button titles:

@"\U0001F6A9 \U0001F4CC \u26F3 \u2690 \u2691 \u274F \u25A4 Test"
@"\U0001F4D6 \U0001F30E \U0001F30F \u25A6 \U0001F3C1 \U0001F332 \U0001F333 \U0001F334 Test"

UIAlertView

enter image description here

Button title:

@"\u26A0 Yes"

UITableViewCell with checkbox and other icons

UITableViewCell

Quits answered 19/3, 2012 at 23:39 Comment(10)
Amazing, but as you said ** you are limited to predefined symbols** but still it's awesome idea, thanks for sharing this.Propeller
can we handle events when we click those images?Anarchic
@Jasmine: Clicking an image is actually clicking the button itself, because the image is its label.Quits
This is really amazing! :)Somerset
@iOSDev: What is the exact reason/statement?Quits
Im sorry, lill misunderstanding regarding the description of apple abt this.. They have shown the screenshots of customized UIActionsheet with UNICode symbols.., but not with this approach of adding symbols. Ur description was absolutely correct. Upvoted. Thanks.Avestan
but how to use these symbols for localized strings? eg. "yes" = "\u26A0 Yes"; shows alert as u26A0 Yes.Armory
@Vaibhav Saran: I never used localization with this approach, but the section "Using Special Characters in String Resources" in the Resource Programming Guide may be helpful: goo.gl/FpLD5 : Though in values you can specifies only "\U followed immediately by up to four hexadecimal digits", you can (especially for longer codes) try to escape the backslash: "yes" = "\\u26A0 Yes";Quits
i have tried. "yes" = "\u26A0 Yes"; appear on UIAlert as u26A0 Yes and "yes" = "\\u26A0 Yes"; on UIAlert appear as \u26A0 YesArmory
@Vaibhav Saran: You can follow the guide and use "yes" = "\U26A0 Yes"; ("\U followed immediately by up to four hexadecimal digits") or prepend the unicode symbol programmatically after retrieving the localized string. Do you localize also symbols?Quits
P
27

Try this way, i hope it may be help you.

UIActionSheet * action = [[UIActionSheet alloc] 
                      initWithTitle:@"Title" 
                      delegate:self 
                      cancelButtonTitle:@"Cancel" 
                      destructiveButtonTitle:nil 
                      otherButtonTitles:@"",nil];

[[[action valueForKey:@"_buttons"] objectAtIndex:0] setImage:[UIImage imageNamed:@"yourImage.png"] forState:UIControlStateNormal];

[[[action valueForKey:@"_buttons"] objectAtIndex:0] setImage:[UIImage imageNamed:@"yourImage_Highlighted.png"] forState:UIControlStateHighlighted];
Provincialism answered 26/5, 2011 at 10:19 Comment(6)
are you positive that this method is legal and i can post my app to the App Store?Propeller
I have same question ? Did submitted to app store with this code ?Papillote
So, will this get rejected or not?Wilmott
Apple considers accessing non-publicly-documented portions of their view hierarchies to be "private API"; this approach risks App Store rejection.Farflung
I have an app with this submitted.Digastric
i have same problem.. my app is crashed in iOS8Showman
D
6

The standard UIActionSheet doesn't support images.

One way to add an image to the UIActionSheet is to add a subview to the UIActionSheet. Just implement the UIActionSheetDelegate method willPresentActionSheet: like this:

- (void)willPresentActionSheet:(UIActionSheet *)actionSheet {
     UIImageView* buttonImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"picturename.png"]];
     // Set the frame of the ImageView that it's over the button.
     [actionSheet addSubview:buttonImage];
     [buttonImage release]; // only if you don't need this anymore
}

I'm not sure if the image responds to touches, but you can build a UIActionSheet like theUIDocumentInteractionController.

Dispel answered 26/5, 2011 at 8:40 Comment(0)
R
5

Here is ones way to do it: https://github.com/levey/LeveyPopListView enter image description here

Rawdin answered 18/7, 2012 at 5:43 Comment(1)
I don't think Android is this refined :|Janel
K
4
- (IBAction)actionSheetButtonPressed:(id)sender {
UIAlertController * view=   [UIAlertController
                             alertControllerWithTitle:@"Share "
                             message:@"Select your current status"
                             preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* online = [UIAlertAction
                         actionWithTitle:@"Facebook"
                         style:UIAlertActionStyleDefault
                         handler:^(UIAlertAction * action)
                         {
                             //Do some thing here
                             [view dismissViewControllerAnimated:YES completion:nil];
                         }];
UIAlertAction* offline = [UIAlertAction
                          actionWithTitle:@"Google+"
                          style:UIAlertActionStyleDefault
                          handler:^(UIAlertAction * action)
                          {
                              [view dismissViewControllerAnimated:YES completion:nil];
                          }];
UIAlertAction* doNotDistrbe = [UIAlertAction
                               actionWithTitle:@"LinkedIn"
                               style:UIAlertActionStyleDefault
                               handler:^(UIAlertAction * action)
                               {
                                   [view dismissViewControllerAnimated:YES completion:nil];
                               }];
UIAlertAction* away = [UIAlertAction
                       actionWithTitle:@"Twitter"
                       style:UIAlertActionStyleDestructive
                       handler:^(UIAlertAction * action)
                       {
                           [view dismissViewControllerAnimated:YES completion:nil];

                       }];
UIAlertAction* cancel = [UIAlertAction
                     actionWithTitle:@"Cancel"
                     style:UIAlertActionStyleDefault
                     handler:^(UIAlertAction * action)
                     {
                     }];

[online setValue:[[UIImage imageNamed:@"facebook.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forKey:@"image"];
[offline setValue:[[UIImage imageNamed:@"google-plus.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forKey:@"image"];
[doNotDistrbe setValue:[[UIImage imageNamed:@"linkedin.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forKey:@"image"];
[away setValue:[[UIImage imageNamed:@"twitter.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forKey:@"image"];

[view addAction:online];
[view addAction:away];
[view addAction:offline];
[view addAction:doNotDistrbe];

[view addAction:cancel];

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

}

Khadijahkhai answered 9/12, 2015 at 6:16 Comment(0)
J
3

You can get action button title from actionSheet object by key "_buttons" and set button image.

UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:@"Title" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Facebook", @"Twitter", @"Google +", @"E - mail", @"Send Message",nil];

[[[actionSheet valueForKey:@"_buttons"] objectAtIndex:0] setImage:[UIImage imageNamed:@"fb_icon1.png"] forState:UIControlStateNormal];
[[[actionSheet valueForKey:@"_buttons"] objectAtIndex:1] setImage:[UIImage imageNamed:@"tweet_icon1.png"] forState:UIControlStateNormal];
[[[actionSheet valueForKey:@"_buttons"] objectAtIndex:2] setImage:[UIImage imageNamed:@"googleplus_icon1.png"] forState:UIControlStateNormal];
[[[actionSheet valueForKey:@"_buttons"] objectAtIndex:3] setImage:[UIImage imageNamed:@"mail_icon.png"] forState:UIControlStateNormal];
[[[actionSheet valueForKey:@"_buttons"] objectAtIndex:4] setImage:[UIImage imageNamed:@"message_icon.png"] forState:UIControlStateNormal];

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

[actionSheet showInView:self.view];
Juvenile answered 4/9, 2014 at 10:29 Comment(1)
Yes. it not support in iOS 8Juvenile
P
2

I just created a class emulating the look of an UIActionSheet using table cells supporting images and text for every row. It also uses blocks for interaction, supports iPhone and iPad, popup from an UITabBarItem on iPad and queueing of multiple sheets. Still in development, but feel free to clone it from Github:

http://github.com/azplanlos/SIActionSheet

Usage is quite simple, here is an example:

SIActionSheet* mySheet = [SIActionSheet actionSheetWithTitle:@"Action Sheet title"
    andObjects:[NSArray arrayWithObjects:
        [SIActionElement actionWithTitle:@"Item 1"
            image:[UIImage imageNamed:@"image"]
            andAction:^{NSLog(@"action 1");}]
    , nil]
    completition:^(int num) {
        NSLog(@"pressed %i", num);
    } cancel:^{NSLog(@"canceled");}];

mySheet.followUpSheet = anotherSheet;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
        [mySheet show];
else
        [mySheet showFromTabBarItem:item inTabBar:tabBar];

If you encounter any problems, please let me know. I hope this helps a lot of people having the same problem like me...

Patronize answered 19/5, 2013 at 16:14 Comment(0)
L
2

For iOS 8, do refer to this

if( [UIAlertController class] ){

    UIAlertController *view     = [UIAlertController alertControllerWithTitle:@"Main Title" 
                                                                      message:@"What do you want to do?"
                                                               preferredStyle:UIAlertControllerStyleActionSheet];

    UIAlertAction *firstAA       = [UIAlertAction actionWithTitle:@"Beep Beep"
                                                           style:UIAlertActionStyleDefault
                                                         handler:^( UIAlertAction *action ){

                                                             [view dismissViewControllerAnimated:YES
                                                                                      completion:nil];
                                                         }];
    [firstAA setValue:[UIImage imageNamed:@"your-icon-name"] forKey:@"image"];
    [view addAction:firstAA];

    UIAlertAction *cancelAA     = [UIAlertAction actionWithTitle:@"Cancel"
                                                           style:UIAlertActionStyleCancel
                                                         handler:^( UIAlertAction *action ){

                                                             [self deselectTableViewRow];

                                                             [view dismissViewControllerAnimated:YES
                                                                                      completion:nil];
                                                         }];
    [view addAction:cancelAA];

    [self presentViewController:view
                       animated:YES
                     completion:nil];
}
else {

    UIActionSheet *sheet    = [[UIActionSheet alloc] initWithTitle:@"What do you want to do?"
                                                          delegate:(id)self
                                                 cancelButtonTitle:nil
                                            destructiveButtonTitle:nil
                                                 otherButtonTitles:nil];

    [sheet addButtonWithTitle:@"title"];

    [[[sheet valueForKey:@"_buttons"] objectAtIndex:0] setImage:[UIImage imageNamed:@"your-icon-name.png"] forState:UIControlStateNormal];

    sheet.cancelButtonIndex = [sheet addButtonWithTitle:@"Cancel"];
    [sheet showInView:self.view];
}
Lang answered 25/2, 2015 at 7:26 Comment(1)
i tried this code but the image tintcolor is changed..... How can i add original image to it???Emmieemmit
S
1

I know it's very late answer, but I found another way to show image in action sheet:

self.actionSheet = [[UIActionSheet alloc] initWithTitle:@"Select Image:" delegate:self cancelButtonTitle:@"Cancel"destructiveButtonTitle:nil otherButtonTitles: @"Image1", @"Image2", @"Image3", @"Image4", @"Image5", @"Image6", @"Image7", @"Image8",@"Image9", @"Image10", @"Image11", @"Image12", @"Image13", @"Image14", @"Image15", nil];

self.actionSheet.tag = 1;
for (id button in [self.actionSheet valueForKey:@"_buttons"])
 {
     UIImageView* buttonImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[button titleForState:UIControlStateNormal]]];
     [buttonImage setFrame:CGRectMake(5, 5,35,35)];
     [button addSubview:buttonImage];
 }

 [self.actionSheet showInView:[UIApplication sharedApplication].keyWindow];
Subbasement answered 26/2, 2014 at 8:51 Comment(1)
Don't use this, it crashes in iOS 8.Trumantrumann
A
1

I found this category extension works in ios7.1 to add an image/icon to the buttons in a UIActionSheet, with some caveats...

@interface UIActionSheet (GSBActionSheetButtons)
- (void)buttonAtIndex:(NSUInteger)index setImage:(UIImage *)image forState:(UIControlState)state;
@end

@implementation UIActionSheet (GSBActionSheetButtons)
- (void)buttonAtIndex:(NSUInteger)index setImage:(UIImage *)image forState:(UIControlState)state
{
    for (UIView* view in self.subviews) {
        if ([view isKindOfClass:[UIButton class]]) {
            if (index-- == 0) {
                UIButton *button = (UIButton*)view;
                [button setImage:image forState:state];
                button.imageView.contentMode = UIViewContentModeScaleAspectFit;
                button.imageEdgeInsets = UIEdgeInsetsMake(2,0,2,0);
                break;
            }
        }
    }
}

And to use it:

[self.sharePopup buttonAtIndex:2 setImage:[UIImage imageNamed:@"twitter.png"] forState:UIControlStateNormal];

The caveats:

  • Although the UIActionSheet does correctly autosize your image to the right height for the button, it does not appear to correspondingly change the imageview width; hence the need for the UIViewContentModeScaleAspectFit to prevent the image from getting squished. However, the imageview frame width is still the original full-size, so if your image was big (or more precisely wide) then you'll get an annoying gap between the centered (shrunk) image and the button text. I've found no way around this; even programmatically adding an explicit width=height constraint to the imageview seems to be ignored!? [any ideas?]. Net outcome, make sure your image is about the right height to begin with (eg about 45 pixels on a iPhone 4S) or you'll get an increasingly large gap between the button image and text.

  • More serious, as soon as you add an image to the button, the UIActionSheet seems to automatically cause the button's text to be bolded (!). I dont know why and dont know how to prevent this [any ideas?]

  • Lastly, this solution relies on the UIActionSheet's subviews to be in the same order as the button are indexed. This is true for a handful of buttons, but (apparantly) when you have a lot of items in your UIActionSheet Apple mucks about with the indexing [but you'll have problems with this anyway in actionSheet:clickedButtonAtIndex: when you try to figure out which button was tapped...]

Oh, the imageEdgeInsets: is optional - I inset each image a couple pixels inside the button so that the images dont touch each other vertically.

[Opinion: given the above oddities, I get the feeling Apple really doesn't want people mucking about with their action sheets. At some point you'll probably have to bite-the-bullet and just implement your own modal popup; there's only so much manhandling these UIActionSheets will accommodate...]

Alyworth answered 23/8, 2014 at 3:19 Comment(0)
P
1
    NSString* strUrl=[MLControl shared].currentServerUrl;
    for( MLServerUrl *title in [MLControl shared].arrServerUrl)  {
        NSString* strShow=title.name;
        if ([strUrl isEqualToString: title.url]) {
            strShow=[NSString stringWithFormat:@"√ %@",strShow];
        }else{
            strShow=[NSString stringWithFormat:@"  %@",strShow];
        }

        [chooseImageSheet addButtonWithTitle:strShow];
    }

   // [[[chooseImageSheet valueForKey:@"_buttons"] objectAtIndex:0] setImage:[UIImage imageNamed:@"ic_check_black_18dp.png"] forState:UIControlStateNormal];
    chooseImageSheet.actionSheetStyle = UIActionSheetStyleDefault;
    [chooseImageSheet showFromRect:btnRc inView:sender animated:YES];
Pithecanthropus answered 18/12, 2014 at 6:5 Comment(0)
H
0

From iOS 8.0 you can use UIAlertController. In UIAlertController, each button item is know as UIAlertAction which add accordingly.

You can check my answer

Hersh answered 19/8, 2016 at 17:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.