Calling an ActionSheet from a TabBar - iphone

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;
}

Instead of opening actionsheet from tabbar
[actionSheet showFromTabBar:self.tabBarController.tabBar];
use this code.
[actionSheet showInView:[UIApplication sharedApplication].keyWindow];

Related

how to change uinavigation controller back button action

I have a UINavigationController and I have to keep the the default back button "the back arrow style" I just want to ask if I can change the back button action without build new one and change its style
AFAIK you cannot change the action of the default back button itself but you can place a UIBarButtonItem as leftBarButtonItem there and assign your own action.
If there is a leftBarButtonItem defined then this is shown and not the default back button.
However, keep the GUI guidelines in mind when doing tricks like this.
No. If you want a custom back button, you have to create a custom UIBarButtonItem, then assign it to the appropriate property:
self.navigationItem.backBarButtonItem = myCustomBackItem;
The back button in UINavigationBar is generated automatically as soon as u Push a new UIView. In order for you to customize the Back button is to Create a new UIToolBar + a UIBarButtonItem with custom view.
Code below is the sample to use a custom UIBarButtonItem in UIToolBar.
// create button
UIButton* backButton = [UIButton buttonWithType:101]; // left-pointing shape!
[backButton addTarget:self action:#selector(backAction) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
// create button item -- possible because UIButton subclasses UIView!
UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
// add to toolbar, or to a navbar (you should only have one of these!)
[toolbar setItems:[NSArray arrayWithObject:backItem]];
navItem.leftBarButtonItem = backItem;
Link below is the design of iOS buttons in PSD format for further modifications.
http://www.chrisandtennille.com/pictures/backbutton.psd
You can make custom button and can make action on it but you can not change default backButton action.....
self.navigationItem.leftBarButtonItem = getBackBtn;
The UINavigationController sends a message to it's delegate when it pushes and pops a ViewController.
You can find out when the back button gets pressed by implementing the following and adding <UINavigationControllerDelegate> in your .h file
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationController.delegate = self;
}
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
self.navigationController.delegate = nil;
}
-(void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated{
//Test here if the View Controller being shown next is right below the current
// ViewController in the navigation stack
//
//Test by:
// 1. comparing classes, or
// 2. checking for a unique tag that you previously assigned, or
// 3. comparing against the [navigationController viewControllers][n-2]
// where n is the number of items in the array
if ([viewController isKindOfClass:NSClassFromString(#"ViewControllerClassThatGetsPushedOnBACK")){
//back button has been pressed
}
if (viewController.tag == myUniqueTagIdentifier){
//back button has been pressed
}
if ([navigationController.viewControllers[navigationController.viewControllers.count-2]==viewController]){
//back button has been pressed
}
}
Apple Docs UINavigationController Class Reference:
The root view controller is at index 0 in the array, the back view
controller is at index n-2, and the top controller is at index n-1,
where n is the number of items in the array.

how is a drop-down list made on the iphone?

I want for a given label Example: Typemarital (possible answers: married, single, PACS, divorced, etc ...) to choose from a predefined list and know how to freeze the answers to a user on a field and not a view (without using the builder interface ) just through the code .
Thanks
It can be made using a button and and a picker view.
1) On click of button, you have to show the picker view and from picker you have to select the value you want. Then from inputAccessoryView of picker view in which you can add a toolbar with done button.
2) On done button click you can get selected value of the picker and hide the picker.
3) The selected value then you can show it into a UILabel.
Hope this helps you.
EDIT:
Here is a very useful tutorial for dropdownmenu in iPhone/iPad:
http://kshitizghimire.com.np/dropdown-in-iphoneipad/
Its quite simple actually.
On click of label create a view and inside it create a table view where you can display list you require, and by simply clicking on cell i.e.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
place text of selected cell to your label and remove your view.
Hope it helps.....
you have to use UITableView.
1) Create a button with title.
2) when clicked on button tableView will be shown.
3) when one of the row of tableview would selected the tableview goes hide and the button title would be row selected in tableview..
You can use UIActionSheet. Add UIPickerView in UIActionSheet.
On tap of a button Try this:
category = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
category.actionSheetStyle = UIActionSheetStyleBlackTranslucent;
UIPickerView *categoryPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0,50, 320, 120)];
categoryPicker.delegate = self;
categoryPicker.dataSource = self;
categoryPicker.showsSelectionIndicator = YES;
[categoryPicker selectRow:1 inComponent:0 animated:NO];
[category addSubview:categoryPicker];
UISegmentedControl *segmentedControlDone = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Done"]];
segmentedControlDone.momentary = YES;
segmentedControlDone.frame = CGRectMake(260, 7, 50, 30);
segmentedControlDone.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControlDone.tintColor = [UIColor blackColor];
[segmentedControlDone addTarget:self action:#selector(actionPickerDone) forControlEvents:UIControlEventValueChanged];
[category addSubview:segmentedControlDone];
// implement data source method of UIPicker also

UIActionSheet delegate method doesn't get called

I have an actionsheet that seems to only call the clickedButtonAtIndex delegate method when I click the "Yes" button, but not on the "No" button... Here's the code:
self.myActionSheet = [[UIActionSheet alloc] initWithTitle:#"Test" delegate:self
cancelButtonTitle:#"No" destructiveButtonTitle:#"Yes" otherButtonTitles:nil];
[self.myActionSheet showInView:self.view];
[myActionSheet release];
then the delegate method:
- (void)actionSheet:(UIActionSheet *)myActionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
[self.myActionSheet dismissWithClickedButtonIndex:1 animated:YES];
return;
}
My breakpoint at the first line of this procedure doesn't get hit unless I touch the
"Yes" button. I have changed this to have the cancelButtonTitle:nil and then put the "No" on another button (otherButtonTitles:#"No", nil). Same thing.
Any help?
Thanks!
Try touching the very top of the No button. Does it work?
Do you have a tab bar or a tool bar? If so, try showing the action sheet from the tab bar or the tool bar. The No button could be partially obscured by the bar.
No, its not a bug.. just a "Real Estate" issue.
take a look at the API.. from the UIActionSheet header...
// show a sheet animated. you can specify either a toolbar, a tab bar, a bar butto item or a plain view. We do a special animation if the sheet rises from
// a toolbar, tab bar or bar button item and we will automatically select the correct style based on the bar style. if not from a bar, we use
// UIActionSheetStyleDefault if automatic style set
- (void)showFromToolbar:(UIToolbar *)view;
- (void)showFromTabBar:(UITabBar *)view;
- (void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_3_2);
- (void)showFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_3_2);
- (void)showInView:(UIView *)view;

How to add a done button over the pickerview?

I want to display a picker view and a done button above the picker view .
I have a custom label which will become first responder . So when it becomes first responder I am displaying a picker view as the input view for my label.
Now I want to have a done button on the picker to dismiss the picker view. I played with the inputAccesoryView property of UIPickerView but did not succeed . inputAccessoryView is possible with UITextView , not sure about the UIPickerView . Here is the link for how it can be done with UITextView
UITextView with “Done” button and “Return” key?
Has any body tried this , if someone knows how to do this for picker , please answer.
Thank you all in advance !!
Add your picker view to an action sheet. First of all make sure youre view controller impliments UIPickerViewDelegate and UIActionSheetDelegate.
Then add this method, and call it when you want to show your picker.
- (void)showPicker {
UIActionSheet *menu = [[UIActionSheet alloc] initWithTitle:#"Pick Value"
delegate:self
cancelButtonTitle:#"Done"
destructiveButtonTitle:nil
otherButtonTitles:nil];
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0,180,0,0)];
pickerView.delegate = self;
pickerView.dataSource = self;
pickerView.showsSelectionIndicator = YES;
[menu addSubview:pickerView];
[menu showInView:self.view.superview];
//Change the height value in your CGRect to change the size of the actinsheet
[menu setBounds:CGRectMake(0,0,320, 615)];
[pickerView release];
[menu release];
}
I think you can try to put the picker inside a view with a 'Done' button and present that view

Different views for different buttons iPhone

I am a newbie in iPhone app development.
I want to develop a iPhone app as when the app is launched there are two buttons displayed for the user.
Button 1 is for User Login .
Button 2 is for User Registration .
How to add view to each of the button, where if Login button is pressed then that view is loaded with few textfields and a button to login in whereas if Registration button is pressed then the registration view is loaded with few textfields and a button to confirm registration.
There are few tutorilas of multiple views but they have only one button on one view and pressing that button the next view is loaded with one button to load the next view and so on and so forth. In my case I want many buttons (atleast 2 at the moment) on one view while app is loaded and then depending upon the button pressed that view is loaded.
Any sample code or tutorial link will be much appreciated.
Thanks in advance.
make one method and registered button event to this method
[button1 addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
[button2 addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
for e.g:
-(IBAction)buttonClicked : (id)sender
{
UIButton * btn = (UIButton *)sender;
if (btn == button1) {
LoginViewController * controller = [[LoginViewController alloc] initWithNibName:# "LoginViewController" bundle:nil];
[self.navigationController pushViewController : controller animated : YES];
[controller release];
} else if (btn == button2) {
RegisterViewController * controller = [[RegisterViewController alloc] initWithNibName:# "RegisterViewController" bundle:nil];
[self.navigationController pushViewController : controller animated : YES];
[controller release];
}
}
you want to make the views in interface builder, then on button one, you will use code like
ViewControllerSubClass1 *viewController1=[[ViewControllerSubClass1 alloc] initWithNibName:#"nibname1" bundle:nil];
[self.navigationController pushViewController:viewController1];
[viewController1 release];
for button two you would use
ViewControllerSubClass2 *viewController2=[[ViewControllerSubClass2 alloc] initWithNibName:#"nibname2" bundle:nil];
[self.navigationController pushViewController:viewController2];
[viewController2 release];