Related
SO I used a tutorial to create an iAd Banner at the bottom of the screen and animate it into and out of the window, however the app is a tab based, and i do not quite know the correct offset, so you could tell me I would appreciate it, however the primary problem, is that the adBanner does not always appear, and when it does sometimes it is just a white box. Here is my code.
In my .h
#interface section3 <ADBannerViewDelegate>{
ADBannerView *adView;
BOOL bannerIsVisible;
}
#property (nonatomic, assign) BOOL bannerIsVisible;
//in the .m in the view did load
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
adView.frame = CGRectOffset(adView.frame, 0.0, 410.0f);
adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
[self.view addSubview:adView];
adView.delegate = self;
self.bannerIsVisible = NO;
-(void)bannerViewDidLoadAd:(ADBannerView *)banner{
if (!self.bannerIsVisible) {
[UIView beginAnimations:#"animateAdBannerOn" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0.0, -50.0f);
[UIView commitAnimations];
self.bannerIsVisible = YES;
}
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
if (self.bannerIsVisible) {
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0.0, 50.0f);
[UIView commitAnimations];
self.bannerIsVisible = NO;
}
}
I am using Xcode 4.2.1
Thank you very much, any help would be appreciated :)
The tabbar is 44px high so u must add to one of the "50" 44 and make 410 to the full screen size of 3.5 inch means to 480 default. That should be the solution.
I am making one animation and in it i Have to make height 0 of one UIView named "subView".
now that subView contain one UIButton and UIImageView.
now i make height 0 by this method on button click
#interface ViewController : UIViewController
{
IBOutlet UIView *suvView;
IBOutlet UIButton *subButton;
IBOutlet UIImageView *imgview;
}
-(IBAction)hide:(id)sender;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:suvView];
[suvView addSubview:subButton];
[suvView addSubview:imgview];
}
-(IBAction)hide:(id)sender
{
[UIView beginAnimations:nil context:suvView];
[UIView setAnimationDuration:0.25];
[suvView setFrame:CGRectMake(0, 94, 320, 0)];
[UIView commitAnimations];
}
#end
but when i make height 0 than View named "subButton" and "imgview" are look as it is.
i want to make Them hidden when subView height is 0.
i am using XCode 4.5
If you want to hide them without resizing: [mainview setClipsToBounds:YES]
You have two methods for doing this :-
Firstly, If you are making the suvViews height 0 then you do not need to remove it. But simply hide the imgview and the subButton like
-(IBAction)hide:(id)sender
{
[UIView beginAnimations:nil context:suvView];
[UIView setAnimationDuration:0.25];
[suvView setFrame:CGRectMake(0, 94, 320, 0)];
[UIView commitAnimations];
subButton.hidden = YES;
imgview.hidden = YES;
}
#end
Also what you can do is reduce the heights of subButton and imgview with the suvView's height like
-(IBAction)hide:(id)sender
{
[UIView beginAnimations:nil context:suvView];
[UIView setAnimationDuration:0.25];
[suvView setFrame:CGRectMake(0, 94, 320, 0)];
[imgview setFrame:CGRectMake(0, x, y, z];
[subButton setFrame:CGRectMake(0, x, y, z];
[UIView commitAnimations];
}
where x,y,z are the coordinates of the imgview and the subButton. Hope this helps.
//try this code for view animation
-(IBAction)hide:(id)sender
{
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationCurveEaseOut
animations:^{
[suvView setFrame:CGRectMake(0, 94, 320, 0)];
}
completion:nil];
}
Add the following line before starting the animation:
subButton.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
imgView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
Or you could do this from the interface builder also by setting the vertical and horizontal resize for each sub view (the button and image view)
Btw you should be using the apple recommended block based animation(if you are using iOS 4.0 and above) rather than beginAnimations: and commitAnimations:.
I know that this question has been asked over and over again, but nothing seems to be working for me. Most of the solutions around are pretty out of date, and the rest are incredibly huge blocks of code that are ten times larger then the actual projects coding. I have a few UITextFields lined up vertically, but when the keyboard launches to edit one, it covers up the text field. I was wondering if there is a simple beginner way to scroll the view up, and then back down when the editing starts and ends?
Thank you.
I have made solutions that work with scroll and non-scroll views using keyboard notification and a detection of the current first responder, but sometimes I use this trivial solution instead: The simple way is to detect the opening keyboard via the text field delegate's textViewDidBeginEditing: method and to move the entire view up. The easiest way to do this is with something along the lines of changing self.view.bounds.origin.y to -100 (or whatever). Use the corresponding textViewShouldEndEditing: method to set it to the opposite, which is 100 in this case. Changing bounds is a relative procedure. After changing it the frame is moved but the bounds origin is still zero.
Since I found it, I use TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding.
It is working great, and is very easy to setup:
Add a UIScrollView into your view controller's xib
Set the scroll view's class to TPKeyboardAvoidingScrollView (still in the xib, via the identity inspector)
Place all your controls within that scroll view
You can also create it programmatically, if you want.
There is a class for the same need inside a UITableViewController ; it is only needed in case you support a version of iOS below 4.3.
#BenLu and other users who are facing problem of the function are never getting called is because of following reason:
As the delegate inbuild function bydefaults return void instead of BOOL this is how it should be as follows:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frame = self.view.frame;
frame.origin.y = -100;
[self.view setFrame:frame];
[UIView commitAnimations];
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frame = self.view.frame;
frame.origin.y = 100;
[self.view setFrame:frame];
[UIView commitAnimations];
}
I spent sometime on this problem and gathered pieces code to create one final solution. My problem was related to UITableView scrolling and keyboard open/close.
You need two partial methods in your cell class:
void EditingBegin(UITextField sender)
{
// Height of tallest cell, you can ignore this!
float tableMargin = 70.0f;
float tableHeight = _tableView.Frame.Size.Height;
float keyBoardHeight = KeyboardHeight();
NSIndexPath[] paths = this._tableView.IndexPathsForVisibleRows;
RectangleF rectLast = this._tableView.RectForSection(paths[paths.Length - 1].Section);
RectangleF rectFirst = this._tableView.RectForSection(paths[0].Section);
float lastCellY = rectLast.Y - rectFirst.Y;
if (lastCellY > tableHeight - keyBoardHeight)
{
float diff = lastCellY - (tableHeight - tableMargin - keyBoardHeight);
this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
}
float cellPosition = this._tableView.RectForSection(this._section).Y;
if (cellPosition > tableHeight - keyBoardHeight)
{
if (this._tableView.ContentInset.Bottom == 0.0f)
{
float diff = cellPosition - (tableHeight - tableMargin - keyBoardHeight);
this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
}
else
{
this._tableView.ScrollToRow(NSIndexPath.FromItemSection(0, this._section), UITableViewScrollPosition.Middle, true);
}
}
}
partial void EditingEnd(UITextField sender)
{
UIView.BeginAnimations(null);
UIView.SetAnimationDuration(0.3f);
this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, 0.0f, 0.0f);
UIView.CommitAnimations();
}
and then in your view controller class:
public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration)
{
base.WillAnimateRotation(toInterfaceOrientation, duration);
float bottom = this.TableView.ContentInset.Bottom;
if (bottom > 0.0f)
{
if (toInterfaceOrientation == UIInterfaceOrientation.Portrait || toInterfaceOrientation == UIInterfaceOrientation.PortraitUpsideDown)
{
bottom = bottom * UIScreen.MainScreen.Bounds.Width / UIScreen.MainScreen.Bounds.Height;
}
else
{
bottom = bottom * UIScreen.MainScreen.Bounds.Height / UIScreen.MainScreen.Bounds.Width;
}
UIEdgeInsets insets = this.TableView.ContentInset;
this.TableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, bottom, 0.0f);
}
}
If you have a UITableView or a UIScrollView it's better to change values for contentOffset instead of making changes to the frame.
Working on Peter's Answer, adding this method to your class works nicely:
- (void)textViewDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGPoint offset = self.tableView.contentOffset;
offset.y += 200; // You can change this, but 200 doesn't create any problems
[self.tableView setContentOffset:offset];
[UIView commitAnimations];
}
That's it, no need to add the textViewDidEndEditing method.
I shouldn't need to say this, but for this to work your UITextField or UITextView must be a delegate of your controller.
Starting with Peter's answer, I developed the following approach in Swift 3.0 under iOS 10.1. I'm doing this for a textView, so I have implemented the UITextViewDelegate functions textViewDidBeginEditing and textViewDidEndEditing where I adjust the view's bounds. As you can see, I set the origin Y value to a small positive number to scroll up and then back to 0 to return to the original position.
Here is the relevant code from my ViewController. You don't need to animate, but it adds a nice touch.
func textViewDidBeginEditing(_ textView: UITextView)
{
if UIScreen.main.bounds.height < 568 {
UIView.animate(withDuration: 0.75, animations: {
self.view.bounds.origin.y = 60
})
}
}
func textViewDidEndEditing(_ textView: UITextView)
{
if UIScreen.main.bounds.height < 568 {
UIView.animate(withDuration: 0.75, animations: {
self.view.bounds.origin.y = 0
})
}
}
i have a scrollview and 3 text fields in this. I have a simple code from my own application :
.h file is :
#import <UIKit/UIKit.h>
#interface AddContactViewController : UIViewController<UITextFieldDelegate, UIScrollViewDelegate>
#property (nonatomic, retain) NSDictionary *dict_contactDetail;
#property (nonatomic, retain) IBOutlet UILabel *lbl_name;
#property (nonatomic, retain) IBOutlet UITextField *txtField_tel;
#property (nonatomic, retain) IBOutlet UITextField *txtField_address;
#property (nonatomic, retain) IBOutlet UITextField *txtField_email;
#property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
#end
.m file :
#import "AddContactViewController.h"
#interface AddContactViewController ()
#end
#implementation AddContactViewController
#synthesize dict_contactDetail;
#synthesize lbl_name, txtField_tel, txtField_email, txtField_address, scrollView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// NSLog(#"dict_contactDetail : %#", dict_contactDetail);
UIBarButtonItem * rightButton = [[UIBarButtonItem alloc] initWithTitle:#"Add" style:UIBarButtonSystemItemDone target:self action:#selector(addEmergencyContact:)];
self.navigationItem.rightBarButtonItem = rightButton;
lbl_name.text = [NSString stringWithFormat:#"%# %#", [dict_contactDetail valueForKey:#"fname"], [dict_contactDetail valueForKey:#"lname"]];
txtField_tel.returnKeyType = UIReturnKeyDone;
txtField_email.returnKeyType = UIReturnKeyDone;
txtField_address.returnKeyType = UIReturnKeyDone;
}
-(void)addEmergencyContact:(id)sender
{
scrollView.frame = CGRectMake(0, 0, 320, 460);
}
#pragma mark - text field delegates
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if([textField isEqual:txtField_tel])
{
[scrollView setContentOffset:CGPointMake(0, 70)];
scrollView.frame = CGRectMake(0, 0, 320, 210);
}
if([textField isEqual:txtField_address])
{
[scrollView setContentOffset:CGPointMake(0, 140)];
scrollView.frame = CGRectMake(0, 0, 320, 210);
}
if([textField isEqual:txtField_email])
{
[scrollView setContentOffset:CGPointMake(0, 210)];
scrollView.frame = CGRectMake(0, 0, 320, 210);
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
scrollView.frame = CGRectMake(0, 0, 320, 460);
[textField resignFirstResponder];
return YES;
}
#end
I like to replicate the form behavior of Safari on the iPhone in my own app. If you enter data in an web form you get a separate UIToolbar (previous, next, done) just above the UIKeyboardView. Same for choosing an option: you get the same UIToolbar just above an UIPickerView.
I am looking for demos / sourcode / ideas how to implement this. Would I create my own subview with that toolbar and textview / pickerview? Is there a more elegant way? Especially something that leverages becomeFirstResponder of UITextfield?
So i created a UIViewCOntroller subclass to manage this.
on that i wrote this function to add.
-(void) addToViewWithAnimation:(UIView *) theView
{
UIView* myview = self.view;
CGRect frame = myview.frame;
frame.origin.y = 420;
myview.frame = frame;
UIView* bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 420)];
bgView.backgroundColor = [UIColor blackColor];
bgView.alpha = 0.6;
backgroundView = bgView;
[theView addSubview: bgView]; // this adds in the dark background
[theView addSubview:self.view]; // this adds in the pickerView with toolbar.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
frame = myview.frame;
frame.origin.y = 420 - frame.size.height;
myview.frame = frame;
[UIView commitAnimations];
}
I then created the view in IB, here is what my class Header looked like at the end of that. (there is also a UItoolbar on the view i just do not have a reference to it in my Controller)
#interface PropertyPickerController : UIViewController {
IBOutlet UIPickerView* Picker;
IBOutlet UIButton* DoneButton;
IBOutlet UIButton* CancelButton;
UIView* backgroundView;
NSArray* SimpleObjects;
id PickerObjectDelegate;
SEL PickerObjectSelector;
}
To then hide the view i use.
-(void) removeFromSuperviewWithAnimation
{
UIView* myview = self.view;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(AnimationDidStop:)];
[UIView setAnimationDuration:0.5];
// set fram below window.
CGRect frame = myview.frame;
frame.origin.y = 420;
myview.frame = frame;
backgroundView.alpha = 0; //fades shade to nothing
[UIView commitAnimations];
}
-(void) AnimationDidStop:(id) object
{
[self.view removeFromSuperview]; //removes view after animations.
[backgroundView removeFromSuperview];
}
And last but not least all the delegate functions for the picker.
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
FBSimpleObject* object = (FBSimpleObject*)[SimpleObjects objectAtIndex:row];
return object.Name;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{ return 1;}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [SimpleObjects count];
}
- (IBAction)CancelButtonClick
{
[self removeFromSuperviewWithAnimation];
}
- (IBAction)DoneButtonClick
{
//This performs a selector when the done button is clicked, makes the controller more versatile.
if(PickerObjectDelegate && PickerObjectSelector)
{
NSMethodSignature* signature = [PickerObjectDelegate methodSignatureForSelector:PickerObjectSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:PickerObjectDelegate];
[invocation setSelector:PickerObjectSelector];
[invocation setArgument:&object atIndex:2];
[invocation retainArguments];
[invocation invoke];
}
}
This is how you do the ToolBar. Basically i use the same concept with a ViewController subclass, and i dont use the standard push view or modal display options. (the example here actually places a Textbox and a toolbar on top of the keyboard.
#interface BugEditCommentController : UIViewController {
UITextView* Comment;
UIToolbar* Toolbar;
}
-(void) addToViewWithAnimation:(UIView*) theView;
To activate this view usually you would call [object becomeFirstResponder];
so if you add this to your view Controller constructor, all you need to do is call [object becomeFirstResponder];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:#selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil];
abd if you implement this method on your controller (defined in the above code)
-(void) keyboardWillShow:(NSNotification *) note
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect toolbarFrame = Toolbar.frame;
CGRect keyboardFrame;
CGPoint keyboardCenter;
[[note.userInfo valueForKey:UIKeyboardCenterEndUserInfoKey] getValue:&keyboardCenter];
[[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &keyboardFrame];
//CGRect toolbarRect = Toolbar.center;
toolbarFrame.origin.y= keyboardCenter.y - ((keyboardFrame.size.height/2) + (toolbarFrame.size.height));
Toolbar.frame = toolbarFrame;
[UIView commitAnimations];
}
-(void) keyboardWillHide:(id) object
{
//you could call [self removeFromSuperviewHere];
}
-(void) removeFromsuperViewWithAnimation
{
[Comment resignFirstResponder];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(AnimationDidStop:)];
CGRect frame = Toolbar.frame;
frame.origin.y = 480;
Toolbar.frame = frame;
[self.view viewWithTag:1].alpha = 0; //fade transparent black background to clear.
[UIView commitAnimations];
}
-(void)AnimationDidStop:(id) object
{
[self.view removeFromSuperview];
}
hope the additional info helps.
I'm looking for the solution for this issue too.
I found this was the best solution, you can use this SCKit to add tool bar to dismiss the UIPickerView or the UIDatePicker as you want.
Following is github link: https://github.com/scelis/SCKit/tree/
Have fun!
I have an application that uses a UITabBarController to switch between modes. When in a certain mode, I'd like to hide the tab bar until the steps of that mode have been completed. Note that I'm not using a navigation controller so I can't use the setHidesBottomBarWhenPushed method on the navigation controller to hide the tab bar.
Prior to iOS 8, When I attempt to hide the tarbar using:
self.tabBarController.tabBar.hidden = YES
the tab bar goes away, but it leaves a 50 pixel blank area at the bottom of the screen where the tab bar used to be. I can't seem to figure out how to fill that area. Anything in the UI that is in that area is clipped and cannot be seen.
Any ideas if this is even possible? I'd really like to stay away from the navigation controller.
Here's my code for that:
This is, of course, mucking with the goings on in the controller's view hierarchy. It could change/break. This uses defined APIs, so Apple won't care, but they won't care about breaking your code, either.
- (void)hideTabBar {
UITabBar *tabBar = self.tabBarController.tabBar;
UIView *parent = tabBar.superview; // UILayoutContainerView
UIView *content = [parent.subviews objectAtIndex:0]; // UITransitionView
UIView *window = parent.superview;
[UIView animateWithDuration:0.5
animations:^{
CGRect tabFrame = tabBar.frame;
tabFrame.origin.y = CGRectGetMaxY(window.bounds);
tabBar.frame = tabFrame;
content.frame = window.bounds;
}];
// 1
}
- (void)showTabBar {
UITabBar *tabBar = self.tabBarController.tabBar;
UIView *parent = tabBar.superview; // UILayoutContainerView
UIView *content = [parent.subviews objectAtIndex:0]; // UITransitionView
UIView *window = parent.superview;
[UIView animateWithDuration:0.5
animations:^{
CGRect tabFrame = tabBar.frame;
tabFrame.origin.y = CGRectGetMaxY(window.bounds) - CGRectGetHeight(tabBar.frame);
tabBar.frame = tabFrame;
CGRect contentFrame = content.frame;
contentFrame.size.height -= tabFrame.size.height;
}];
// 2
}
Edit:
An anonymous user has suggested the following addition for 7.0 (i have not tested this, and could not say whether it is a workaround or an ideal implementation):
// 1. To Hide the black line in IOS7 only, this extra bit is required
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
[self.tabBarController.tabBar setTranslucent:YES];
}
// 2. For IOS 7 only
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
[self.tabBarController.tabBar setTranslucent:NO];
}
Edit: Entirely untested in 8.x and likely lacking in some layouts.
Like Steve, I haven't found a clean way to do this (even though Apple Photopicker does something similar). Here is what I have done:
if (systemAction)
{
// Reveal tab bar back
CGRect bounds = [[UIScreen mainScreen] bounds];
CGRect tabBarFrame = self.tabBarController.tabBar.frame;
self.tabBarController.view.frame = CGRectMake(0,0,bounds.size.width,bounds.size.height);
self.toolBar.hidden = YES;
systemAction = NO;
}
else
{
//hide tab bar
CGRect bounds = [[UIScreen mainScreen] bounds];
CGRect tabBarFrame = self.tabBarController.tabBar.frame;
CGRect navigationBarFrame = self.navigationController.navigationBar.frame;
self.tabBarController.view.frame = CGRectMake(0,0,bounds.size.width,bounds.size.height+tabBarFrame.size.height);
self.toolBar.hidden = NO;
CGRect frame = self.toolBar.frame;
frame.origin.y = bounds.size.height - frame.size.height - navigationBarFrame.size.height;
self.toolBar.frame = frame;
systemAction = YES;
}
What it is doing is pushing the view down so I can display a toolbar (and not hiding it). Obviously this is for only the 'root view' of a tabbar + navigation controller. For any subsequent views you can set the 'hidesBottomBarWhenPushed' on the viewcontroller you are pushing.
I tried a number of the solutions above, but no joy in iOS 8. I find that setting in viewWillAppear the following works for me. Should work in iOS 7 as the extendedLayoutIncludesOpaqueBars was introduced then.
self.extendedLayoutIncludesOpaqueBars = true
self.tabBarController?.tabBar.isHidden = true
self.tabBarController?.tabBar.isOpaque = true
and if you need to turn tabBars on again when you leave to use the following in viewWillDisappear.
self.tabBarController?.tabBar.isHidden = false
self.tabBarController?.tabBar.isOpaque = false
I use this to allow a return from a transition to keep the TabBar hidden. Not used it in a button action but if like me you find nothing above now works, this could be the basis of a programmable solution.
It's a bit late in the day, but of all the answers to the question that I've trawled through this afternoon, this is the one that worked best for me.
How to hide uitabbarcontroller
// Method call
[self hideTabBar:self.tabBarController];
// Method implementations
- (void)hideTabBar:(UITabBarController *) tabbarcontroller
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 480, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 480)];
}
}
[UIView commitAnimations];
}
- (void)showTabBar:(UITabBarController *) tabbarcontroller
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
NSLog(#"%#", view);
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 431, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 431)];
}
}
[UIView commitAnimations];
}
I use only this single line to achieve this. I use prepareForSegue method before showing the view controller having the tab bar.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"showLogin"]){
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
}
}
I had worked on almost the same case, actually used the code from http://www.developers-life.com/hide-uitabbarcontrolleruitabbar-with-animation.html and made it better according to my needs, this might help others too.
I am using a UISplitViewController as the root view controller and its detail portion is a UITabBarController, I had to hide the tabbar in portrait mode:
// In UITabBarController's custom implementation add following method,
// this method is all that will do the trick, just call this method
// whenever tabbar needs to be hidden/shown
- (void) hidetabbar:(NSNumber*)isHidden {
UITabBarController *tabBarController=self;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
CGRect tabbarFrame=CGRectZero;
for(UIView *theView in tabBarController.view.subviews) {
//NSLog(#"%#", view);
if([theView isKindOfClass:[UITabBar class]]) {
tabbarFrame=theView.frame;
if ([isHidden boolValue]) {
tabbarFrame=CGRectMake(tabbarFrame.origin.x,
tabBarController.view.frame.size.height,
tabbarFrame.size.width,
tabbarFrame.size.height);
} else {
tabbarFrame=CGRectMake(tabbarFrame.origin.x,
tabBarController.view.frame.size.height - tabbarFrame.size.height,
tabbarFrame.size.width,
tabbarFrame.size.height);
}
theView.frame=tabbarFrame;
break;
}
}
for(UIView *theView in tabBarController.view.subviews) {
if(![theView isKindOfClass:[UITabBar class]]) {
CGRect theViewFrame=theView.frame;
if ([isHidden boolValue]) {
theViewFrame=CGRectMake(theViewFrame.origin.x,
theViewFrame.origin.y,
theViewFrame.size.width,
theViewFrame.size.height + tabbarFrame.size.height);
} else {
theViewFrame=CGRectMake(theViewFrame.origin.x,
theViewFrame.origin.y,
theViewFrame.size.width,
theViewFrame.size.height - tabbarFrame.size.height);
}
theView.frame=theViewFrame;
}
}
[UIView commitAnimations];
}
I used following code to call the hidetabbar: method
//In my UISplitViewController's custom implementation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
#synchronized(self){
//change the self.splitDetailController to your UITabBarController's object
[self.splitDetailController
performSelector:#selector(hidetabbar:)
withObject:[NSNumber numberWithBool:UIInterfaceOrientationIsLandscape(interfaceOrientation)]
afterDelay:0.5];
}
return YES;
}
I tested this code to work in simulator only, let me know if it works on device too ;-)
Do you have the autoResizingMask set on the sub view?
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Something like that should do the trick and allow the view sitting atop the stack to re-size.
The obvious solution, keeping your original architecture, would have been to present that view modally:
- (void)tabBarController:(UITabBarController *)tb
didSelectViewController:(UIViewController *)vc {
if (tb.selectedIndex == MODALONE) {
UIViewController* mod =
[[UIViewController alloc] initWithNibName: #"ModalView"
bundle: nil];
[tb presentModalViewController:mod animated:NO];
[mod release];
}
}
The view now covers the entire screen (except for the status bar is there is one) including the tab bar, so it looks as if the tab bar has gone away in response to the user pressing that tab bar item.
autoresizing mask has an enumeration. Try to set all the options and check if autoresize subviews option is checked in parent view
You can create Tabbar Category and show/Hide easily. and you can access full view.
create category #import "UITabBarController+HideTabBar.h"
#implementation UITabBarController (HideTabBar)
- (void)hideTabBarAnimated:(BOOL)animated
{
CGRect statusbarFrame = [UIApplication sharedApplication].statusBarFrame;
CGRect tabBarControllerFrame = self.view.frame;
if (statusbarFrame.size.height>20)
{
tabBarControllerFrame.size.height = screenSize.size.height + self.tabBar.frame.size.height - 20.0;
}
else
{
tabBarControllerFrame.size.height = screenSize.size.height + self.tabBar.frame.size.height ;
}
if (animated) {
[UIView animateWithDuration:0.2 animations:^{
[self.view setFrame:tabBarControllerFrame];
} completion:^(BOOL finished) {
}];
}
else
[self.view setFrame:tabBarControllerFrame];
}
- (void)showTabBarAnimated:(BOOL)animated {
CGRect statusbarFrame = [UIApplication sharedApplication].statusBarFrame;
CGRect tabBarControllerFrame = self.view.frame;
if (statusbarFrame.size.height>20)
{
tabBarControllerFrame.size.height = screenSize.size.height - 20.0;
}
else
{
tabBarControllerFrame.size.height = screenSize.size.height ;
}
if (animated) {
[UIView animateWithDuration:0.2 animations:^{
[self.view setFrame:tabBarControllerFrame];
} completion:^(BOOL finished) {
}];
}
else
[self.view setFrame:tabBarControllerFrame];
}
#end
Note : use statusbarFrame is used when hotspot or call is ON so tabbar would not cut down.
Now Import category in which you class you want to use methods and just call below methods to hide or show tabbar.
[self.tabBarController hideTabBarAnimated:YES];
[self.tabBarController showTabBarAnimated:YES];
Hope this Helps.
Hope this works.
#interface UITabBarController (Additions)
-(void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated;
#end
#implementation UITabBarController (Additions)
-(void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated
{
if (animated)
{
[UIView beginAnimations:nil context:nil];
}
if (hidden)
{
self.tabBar.frame = CGRectMake(self.tabBar.frame.origin.x, self.tabBar.superview.frame.size.height, self.tabBar.bounds.size.width, self.tabBar.bounds.size.height);
}
else
{
self.tabBar.frame = CGRectMake(self.tabBar.frame.origin.x, self.tabBar.superview.frame.size.height - self.tabBar.frame.size.height + 10, self.tabBar.bounds.size.width, self.tabBar.bounds.size.height);
}
if (animated)
{
[UIView commitAnimations];
}
}
Here is my solution (my tab view controller is inside navigation controller for good measure)... So I have subclassed UITabBarController and did this... exposing -setTabBarHidden: method
- (void)setTabBarHidden:(BOOL)hidden {
_tabBarHidden = hidden;
[UIView performWithoutAnimation:^{
[self adjustViews];
}];
}
- (void)adjustViews {
if ( _tabBarHidden ) {
CGRect f = self.tabBar.frame;
// move tab bar offscreen
f.origin.y = CGRectGetMaxY(self.view.frame);
self.tabBar.frame = f;
// adjust current view frame
self.selectedViewController.view.frame = self.view.frame;
} else {
CGRect f = self.tabBar.frame;
// move tab bar on screen
f.origin.y = CGRectGetMaxY(self.view.frame) - (CGRectGetMaxY(self.tabBar.bounds) + CGRectGetMaxY(self.navigationController.navigationBar.frame));
self.tabBar.frame = f;
// adjust current view frame
f = self.view.bounds;
f.size.height -= CGRectGetMaxY(self.tabBar.bounds);
self.selectedViewController.view.frame = f;
}
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
[UIView performWithoutAnimation:^{
[self adjustViews];
}];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[UIView performWithoutAnimation:^{
[self adjustViews];
}];
}
put the statement in the init method of the UIViewController
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.hidesBottomBarWhenPushed = true
setupDependencyConfigurator()
}
See this thread:
Show/Hide TabBarController in iphone
In summary, you can see an example of this behavior in this sample code:
http://developer.apple.com/iphone/library/samplecode/TheElements/index.html
Why are you not using a navigation controller. It's a lot easier to hide the nav bar than the tab bar...
Just made the following code in Monotouch inside a subclass of UITabBarController:
public void ShowTabBar()
{
UIView.BeginAnimations("Anim");
UIView.SetAnimationDuration(0.25f);
this.View.Subviews[0].Frame = new RectangleF(0f, 0f, 320f, 431f);
this.TabBar.Frame = new RectangleF(0f, 431f, 320f, 49f);
this.TabBar.Hidden = false;
UIView.CommitAnimations();
}
public void HideTabBar()
{
UIView.BeginAnimations("Anim");
UIView.SetAnimationDuration(0.25f);
this.View.Subviews[0].Frame = new RectangleF(0f, 0f, 320f, 480f);
this.TabBar.Frame = new RectangleF(0f, 481f, 320f, 510f);
this.TabBar.Hidden = true;
UIView.CommitAnimations();
}