I have a tab bar with 4 buttons (Home, Visits, Share, More). I want the "Share" button in my tab bar to call an actionsheet which has the appropriate buttons to select the particular channels I want the user to be able to distribute links to the app (Facebook, Twitter, Email, etc.).
I'm able to do this using Storyboard but I have to create a unique (blank) view controller that is linked to the "Share" button in the tab bar. I put the following code within the viewDidAppear method to display the actionsheet when the "Share" button is selected:
int selectedTab = self.tabBarController.selectedIndex;
if (selectedTab == 2)
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Share Your Visit with Friends!" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Facebook", @"Twitter", @"Email eduLaunchpad", nil];
[actionSheet showFromTabBar:self.tabBarController.tabBar];
}
When I close the actionsheet, I then return by default to the home view:
[self.tabBarController setSelectedIndex:0];
While this works, it isn't optimal from a user perspective. I would prefer the actionsheet to appear over the particular view that was displaying when the "Share" button was selected. For example, if the user was on the "Visits" view and selected "Share" from the tab bar, I would like the actionsheet to appear over the top of the visits view with that view being visible behind the actionsheet.
Am I able to achieve this using Storyboard? Or do I need a custom tab bar in order to implement this functionality? If a custom tab bar is required, I would appreciate some guidance/insight into how to implement that including the custom tab bar as well as the actionsheet from the tab bar.
Thanks in advance!
I needed this, too, googled around, and eventually built the following category on UITabBarController.
The trick to getting the action sheet to appear on the current tab is that you never want to actually visit that action-sheet-presenting tab. Cover the tab bar in that position with a UIButton which initiates the action sheet.
Paint your tab bar as you normally would in storyboard, leaving an empty bar item at the position where the special behavior is to occur. Then add this category...
// UITabBarController+Button.h
@interface UITabBarController (Button) <UIActionSheetDelegate>
- (void)replaceItemAtIndex:(NSUInteger)index withButtonImage:(UIImage*)buttonImage;
@end
// UITabBarController+Button.m
#import "UITabBarController+Button.h"
#define kBUTTON_TAG 4096
@implementation UITabBarController (Button)
- (void)replaceItemAtIndex:(NSUInteger)index withButtonImage:(UIImage*)buttonImage {
UIButton *button = (UIButton *)[self.view viewWithTag:kBUTTON_TAG];
if (!button) {
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = kBUTTON_TAG;
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
UITabBar *bar = self.tabBar;
CGFloat width = bar.frame.size.width / bar.items.count;
button.frame = CGRectMake(index*width, bar.frame.origin.y, width, bar.frame.size.height);
[self.view addSubview:button];
}
}
#pragma mark - Handle button tap
- (void)buttonTapped:(id)sender {
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Action Sheet:"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"Action A", @"Action B", @"Action C", nil];
[sheet showFromTabBar:self.tabBar];
}
Call it with an index < tabBar.items.count and an image for the button. If it's your app's root vc, you can call it as follows:
#import "the category i suggest above"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// whatever else you do in here, then
NSLog(@"%@", self.window.rootViewController); // make sure this is a UITabBarController
// if it is, then ...
UITabBarController *tbc = (UITabBarController *)self.window.rootViewController;
[tbc replaceItemAtIndex:2 withButtonImage:[UIImage imageNamed:@"some image name"]];
return YES;
}