Programatic UIViews being rotated correctly - iphone

I have been doing pretty much all of my User Interface programmatically with slight alterations being performed in Interface Builder.. but 99% of all the UI is exclusively done in code, because I feel there is a certain amount of flexibility gained by doing it this way.
However I am now having issues dealing with the rotation of the device, as I have several UIViews being added as subviews I am faced with a rotational problem as this is how I declare the views generally
htmlTest.webViewTest.frame = CGRectMake(4.0, 4.0, 312.0, 363.0);
and because of this fixed CGRectMake when the device is rotated the view stays the same size and dosent fit the orientation of the view properly.
So I have worked on a solution which is in my opinion horrible.. There are a couple of views that I animate in and users can select options from them then I animate them out.. but they need to be able to handle loading in either portrait or landscape and then if while they are loaded they need to be able to handle a rotation from either orientation to the other.
This is how I have done one of the views.
#pragma createAwesomeJumpBar
- (void)jumpBarButtonPosition:(int)changeView
{
// ChangeView is used to check if the this method is being called from a device rotation or from a button press (0, being rotation and 1, being tabbarButton touch
// if tabbar selected
if (changeView == 1) {
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait)
{
if (![jumpBarContainerPortrait superview]) {
// load portrait view
jumpBarContainerPortrait = [[UIView alloc] initWithFrame:CGRectMake(0.0, 480.0, 320, (jumpBarHeightPortrait + 49.0))];
jumpBarContainerPortrait.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
// add jumpbar container to view
[self.view insertSubview:jumpBarContainerPortrait belowSubview:actionTabBar];
[UIView animateWithDuration:0.6
delay:0.0f
options:UIViewAnimationCurveEaseIn
animations:^{
jumpBarContainerPortrait.frame = CGRectMake(0.0, (367 - jumpBarHeightPortrait), 320.0, (jumpBarHeightPortrait + 49.0)); // display jumpBar
} completion:^(BOOL finished) {
if (finished) {
NSLog(#"YAY!");
}
}];
}
else if ([jumpBarContainerPortrait superview]) {
//unload portrait view
[UIView animateWithDuration:0.6
delay:0.0f
options:UIViewAnimationCurveEaseIn
animations:^{
jumpBarContainerPortrait.frame = CGRectMake(0.0, 480.0, 320.0, (jumpBarHeightPortrait + 49.0)); // display jumpBar
// remove selected tabButton highlight
[actionTabBar setSelectedItem:nil];
} completion:^(BOOL finished) {
if (finished) {
// remove subView for superView
[jumpBarContainerPortrait removeFromSuperview];
}
}];
}
}
else if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight)
{
if (![jumpBarContainerLandscape superview]) {
// load landscape view
jumpBarContainerLandscape = [[UIView alloc] initWithFrame:CGRectMake(0.0, 320, 480.0, (jumpBarHeightLandscape + 49.0))];
jumpBarContainerLandscape.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
// add jumpbar container to view
[self.view insertSubview:jumpBarContainerLandscape belowSubview:actionTabBar];
[UIView animateWithDuration:0.6
delay:0.0f
options:UIViewAnimationCurveEaseIn
animations:^{
jumpBarContainerLandscape.frame = CGRectMake(0.0, (207 - jumpBarHeightLandscape), 480.0, (jumpBarHeightLandscape + 49.0)); // display jumpBar
} completion:^(BOOL finished) {
if (finished) {
NSLog(#"YAY!");
}
}];
}
else if ([jumpBarContainerLandscape superview]) {
// remove landscape view
[UIView animateWithDuration:0.6
delay:0.0f
options:UIViewAnimationCurveEaseIn
animations:^{
jumpBarContainerLandscape.frame = CGRectMake(0.0, 320, 480.0, (jumpBarHeightLandscape + 49.0)); // display jumpBar
[actionTabBar setSelectedItem:nil];
} completion:^(BOOL finished) {
if (finished) {
// remove subView for superView
[jumpBarContainerLandscape removeFromSuperview];
}
}];
}
}
}
// if device rotated selected
else if (changeView == 0) {
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait)
{
if([jumpBarContainerLandscape superview])
{
// Device is changing from landscape to protrait change views to fit
// load landscape view
jumpBarContainerPortrait = [[UIView alloc] initWithFrame:CGRectMake(0.0, (367 - jumpBarHeightPortrait), 320.0, (jumpBarHeightPortrait + 49.0))];
jumpBarContainerPortrait.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
jumpBarContainerPortrait.alpha = 1.0;
// add jumpbar container to view
[UIView transitionFromView:jumpBarContainerLandscape
toView:jumpBarContainerPortrait
duration:animationSpeed
options:UIViewAnimationOptionTransitionCrossDissolve
completion:NULL];
[self.view insertSubview:jumpBarContainerPortrait belowSubview:actionTabBar];
}
}
else if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight)
{
if ([jumpBarContainerPortrait superview])
{
// Device is changing from portrait to landscape change views to fit
// load landscape view
jumpBarContainerLandscape = [[UIView alloc] initWithFrame:CGRectMake(0.0, (207 - jumpBarHeightLandscape), 480.0, (jumpBarHeightLandscape + 49.0))];
jumpBarContainerLandscape.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
jumpBarContainerLandscape.alpha = 1.0;
// add jumpbar container to view
[UIView transitionFromView:jumpBarContainerPortrait
toView:jumpBarContainerLandscape
duration:animationSpeed
options:UIViewAnimationOptionTransitionCrossDissolve
completion:NULL];
[self.view insertSubview:jumpBarContainerLandscape belowSubview:actionTabBar];
}
}
}
}
in this example, I have two views landscape and portrait, obviously as the names go each are for their respective orientations.. the logic above goes along the lines of this
if tabbarselected
if !view visible
if device orientation portrait
animate in portrait view.
if device orientation landscape
animate in landscape view
if view visible
if device orientation portrait
animate out portrait view
clear tabbar
if device orientation landscape
animate out landscape view
clear tabbar
if !tabbarselected //meaning listener has identified orientation of device has changed
if device orientation portrait
unload portrait
load landscape
if device orientation landscape
unload landscape
load portrait
I would like to know if there is an easier way than going through all of this hassle! I am still fairly inexperienced so this was my best attempt.. I am hoping someone out there knows of an easier approach than having to do all of this leg work to get views being added to other views as subviews adjusting for orientation properly
any help would be greatly appreciated! I'm desperate lol :)

See the autoresizingMask documentation. Gives you all the same springs and struts control that you have in Interface Builder. E.g.:
CGRect frame = CGRectMake(margin, margin, self.view.frame.size.width - margin * 2, self.view.frame.size.height - margin * 2);
UIView *mySubview = [[UIView alloc] initWithFrame:frame];
[self.view mySubview];
mySubview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Also, if you decide that autoresizingMask is not enough (for example, when you're moving objects with respect to each other to really fine tune the portrait versus landscape orientation), I'd suggest you do this layout process in viewWillLayoutSubviews for iOS5, (or willAnimateRotationToInterfaceOrientation in iOS4 or earlier). This way you don't need to animate the change yourself and the animation will be done in conjunction with the rest of the screen rotation animation.

Related

scale animation from scroll sub view (Image view ) to UIwindow and zoom

May be this Question may be duplicate but i really need your help..
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
NewFeedDetailVC *nextViewController = [[NewFeedDetailVC alloc] initWithNibName:#"NewFeedDetailVC" bundle:[NSBundle mainBundle]];
nextViewController.originRect = imgFrame;
nextViewController.currentscrolloffset=aStylizedView.contentOffset.y;
[window addSubview:nextViewController.view];
[UIView animateWithDuration:0.5
animations:^{
nextViewController.view.frame = CGRectMake(0, 20, 320, ScreenHeight-20);
}
completion:^(BOOL finished){
}];
above is demo code i have tried to make zoom animation before push ..
imgFrame is image on which user will tap
When user click right top orange (four square) button ,and code as below
[UIView animateWithDuration:0.5
animations:^{
self.view.frame=self.originRect;
}
completion:^(BOOL finished){
[test removeFromSuperview];
[self.view removeFromSuperview];
}];
view should be pop out with zoom in animation to there parent frame but i am not able to perform smooth transition and image suppose to be same as parent frame and just black view is scaling to original frame, and another issue is you can observe animation is not clipping out in navigation control even if Its frame is clipping in original scroll view.
Thanks

Animating UIViews to get crossfade effect not working very well

I have successfully created a icon menu that displays from a tabBar selection. You can view this menu in either Portrait or Landscape.
because of the space on the screen I have made it so that in portrait you can view 4x4 icons.. however due to sizing when viewed in landscape this dose not work that well.. so I have made it so that you can view 2 rows of 6 and 1 row of 4. because of this, I have decided to create two UIViews for the menu, when the device rotates I switch between the two views.
i.e. if Portrait current and device is rotated load Landscape and unload Portrait and vice versa.
This is the code I am using to change views on the device rotation, this works perfectly fine (might not be the best code but its the best I could do)
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait)
{
if([jumpBarContainerLandscape superview])
{
// Device is changing from landscape to protrait change views to fit
// load landscape view
jumpBarContainerPortrait = [[UIView alloc] initWithFrame:CGRectMake(0.0, (367 - jumpBarHeightPortrait), 320.0, (jumpBarHeightPortrait + 49.0))];
jumpBarContainerPortrait.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
jumpBarContainerPortrait.alpha = 0.0;
// add jumpbar container to view
[self.view insertSubview:jumpBarContainerPortrait belowSubview:actionTabBar];
[UIView animateWithDuration:0.2
delay:0.0f
options:UIViewAnimationCurveEaseIn
animations:^{
jumpBarContainerLandscape.alpha = 0.0;
} completion:^(BOOL finished) {
if (finished) {
}
}];
[UIView animateWithDuration:0.2
delay:0.0f
options:UIViewAnimationCurveEaseIn
animations:^{
jumpBarContainerPortrait.alpha = 1.0;
} completion:^(BOOL finished) {
if (finished) {
// remove subView for superView
[jumpBarContainerLandscape removeFromSuperview];
}
}];
}
}
else if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight)
{
if ([jumpBarContainerPortrait superview])
{
// Device is changing from portrait to landscape change views to fit
// load landscape view
jumpBarContainerLandscape = [[UIView alloc] initWithFrame:CGRectMake(0.0, (207 - jumpBarHeightLandscape), 480.0, (jumpBarHeightLandscape + 49.0))];
jumpBarContainerLandscape.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
jumpBarContainerLandscape.alpha = 0.0;
// add jumpbar container to view
[self.view insertSubview:jumpBarContainerLandscape belowSubview:actionTabBar];
// fade out
[UIView animateWithDuration:0.2
delay:0.0f
options:UIViewAnimationCurveEaseIn
animations:^{
jumpBarContainerPortrait.alpha = 0.0;
} completion:^(BOOL finished) {
if (finished) {
}
}];
// fade in
[UIView animateWithDuration:0.2
delay:0.0f
options:UIViewAnimationCurveEaseIn
animations:^{
jumpBarContainerLandscape.alpha = 1.0;
} completion:^(BOOL finished) {
if (finished) {
// remove subView for superView
[jumpBarContainerPortrait removeFromSuperview];
}
}];
}
}
Now the issue I am having is that the animation between the two UIViews is quite ugly, its not very smooth you can see the two different views on the animation etc which is undesirable.. I was wondering if anyone could think of a nice way to crossfade between the two making it look abit smoother etc...
any help would be greatly appreciated.
EDIT:
So I have just tried to create a CATransaction, however I have an error on one line giving me this error No visible #interface for 'UIView' declares the selector 'jumpBarContainerPortrait' I have added a comment to the line where I get this error below.. any help would be appreciated
[CATransaction begin];
CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.duration = 3.50;
[self.view insertSubview:jumpBarContainerPortrait belowSubview:actionTabBar];
[[self.view jumpBarContainerPortrait] addAnimation:animation forKey:#"Fade"]; // Error is happening here!
[CATransaction commit];
Instead of your separate fade in and fade out animations, use the UIView method "transitionFromView". Here's an example:
[UIView transitionFromView:jumpBarContainerLandscape
toView:jumpBarContainerPortrait
duration:crossDissolveTime
options:UIViewAnimationOptionTransitionCrossDissolve
completion:NULL];

Animated UIPickerView not rotating in landscape mode

I have a UIPickerView that animates up and down in a UITableViewController. I adapted an example from apple (DateCell). The UIPickerView is created programmatically, no nib files.
In Portrait mode everything looks nice. When I rotate the simulator (I not testing on the device), the UITableView rotates well, but the picker remains were it was. I read tons of threads about that topic and many developers seem to have problems with pickers behaving weird in landscape mode but at least their pickers rotate. I made a subclass of UIPickerView as described in this link: http://www.llamagraphics.com/developer/using-uidatepicker-landscape-mode, but it didn't help for the rotation issue.
I tried to rotate the picker with a transform but it looked very weird, like broken.
I'm suspecting that the problem is that I'm using the picker inside of a UITableViewController, and so I add it as a subview of self.view.window. If I try to add the picker as a subview of self.view, only a white frame (without any picker) appears.
Any suggestions?
The initialization code in the UITableViewController subclass:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.pickerView.superview == nil)
{
//Initialization code
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect initFrame = orientation == UIInterfaceOrientationPortrait ? CGRectMake(0, 0, 320, 200) : CGRectMake(0, 0, 480, 160);
self.pickerView = [[RotatingUIPickerView alloc] initWithFrame:initFrame];
[self.pickerView setDelegate:self];
[self.pickerView setShowsSelectionIndicator:YES];
[self.pickerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin];
[self.view.window addSubview:self.pickerView];
// compute the start frame
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
CGSize pickerSize = [self.pickerView sizeThatFits:CGSizeZero];
CGRect startRect = CGRectMake(0.0,
screenRect.origin.y + screenRect.size.height,
pickerSize.width, pickerSize.height);
[self.pickerView setFrame:startRect];
// compute the end frame
CGRect pickerRect = CGRectMake(0.0,
screenRect.origin.y + screenRect.size.height - pickerSize.height,
pickerSize.width,
pickerSize.height);
// start the slide up animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
// we need to perform some post operations after the animation is complete
[UIView setAnimationDelegate:self];
[self.pickerView setFrame:pickerRect];
[UIView commitAnimations];
}
}
Implementation of UIPicker subclass as described on the link above:
- (id)initWithFrame:(CGRect)frame
{
if (self == [super initWithFrame:frame])
{
for (UIView * subview in self.subviews)
{
[subview setFrame:self.bounds];
}
}
return self;
}
- (id) initWithCoder:(NSCoder *)aDecoder
{
if (self == [super initWithCoder: aDecoder])
{
for (UIView * subview in self.subviews)
{
[subview setFrame:self.bounds];
}
}
return self;
}
By executing:
[self.view.window addSubview:self.pickerView];
you are adding pickerView as a subview of your UIWindow. I don't know how the main UIWindow can be rotated, if it can be.
When you are adding pickerView to the view
[self.view addSubview:self.pickerView];
you get problems due to the view being a UITableView.
What I suggest is adding pickerView to some intermediate UIView, added as subview to UIWindow and to which you add the UITableView. This intermediate UIView would also have a UIViewController associated to it so that shouldAutorotateToInterfaceOrientation can return the proper value to have auto rotation working.

iPhone rotation issue

I am working to force a view into landscape mode, and have picked up all kinds of cool tips to make this happen, but am stuck on one item that is left on the screen.
I have my XIB file laid out in landscape, and in my code I create the view controller normally:
RedeemViewController *aViewController = [[RedeemViewController alloc] initWithNibName:#"RedeemViewController" bundle:nil];
aViewController.hidesBottomBarWhenPushed = YES;
aViewController.wantsFullScreenLayout = YES;
[[self navigationController] pushViewController:aViewController animated:YES];
Inside the controller viewDidLoad I complete the following:
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
[[self navigationController] setNavigationBarHidden:YES animated:YES];
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:.75];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}
[UIView commitAnimations];
What I end up with is a perfectly rotated view, with a grey vertical bar on the left side (see pic).
alt text http://taxhelp.net/vert_bar.png
So to the question, how do I get rid of the bar?
Edit: I am pretty sure this is the navigation bar that is not being hidden.
Your bounds rectangle is created with the origin at (0, -20). Change that to (0, 0) and you should be rid of the offset and have the view filling the screen.

Iphone: Is it possible to hide the TabBar? (Pre-iOS 8)

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