UITabBar leaves a white rectangle when hidden - iphone

I have been unable to google an acceptable solution to this that can be applied to my project.
My app is a graphing tool that has three tabs; one for the graph itself and the other two are for browse/search functions for things that can be added to the graph. All tabs are navigation controllers.
The tab for the graph itself, when in portrait mode, displays a small preview of the graph and lists details of each entity that is on the graph below, and displays the tab bar at the bottom.
When the user rotates into landscape mode the graph turns full screen and everything else, including the tab bar, disappears. This is where I'm having the problem, as the GLView for my graph is always obscured by a white rectangle where the tab bar was.
I have tried changing the size of the navigation controllers view to full screen, changing the size of the tab bar controllers' view to full screen, changing the frame size of the tab bar itself to CGRect(0,0,0,0), becoming emotionally distraught, banging my fists on the desk, shouting abusive language at the MacBook, etc; all to no avail.
How can I make it work?

I had this problem, and I've resolved it by changing tabbar's subview frame for my content view (there are 2 subviews in tab bar - content view (#0) and bar view (#1)):
[[self.tabBarController.view.subviews objectAtIndex:0] setFrame:FULLSCREEN_FRAME];

I had the same problem and found the answer here : UIView doesn't resize to full screen when hiding the nav bar & tab bar
just resize the tabbarcontroller view this when you hide the tabbar :
tabBarController.view.frame = CGRectMake(0, 0, 320, 480);

It seems to have the problem with hiding the Bottom bar as Tab bar.... which I was facing and googled a lot for this.I consider it as a bug with this tab bar.Then also....we can use some trick.....
You can try for this and will definitely help if you are trying to hide the tab bar and which leaves the white space..
for the hell of coding you need to write just
[self setHidesBottomBarWhenPushed:YES];
when you are pushing to other view,where you don't need the Tab bar just write it
twitDetObj=[[TwitDetail alloc] initWithNibName:#"TwitDetail" bundle:nil];
[self.navigationController pushViewController:twitDetObj animated:YES];
self.hidesBottomBarWhenPushed=YES;
[twitDetObj release];
Hope this will work for you.....

This one works for me:
[[self.tabBarController.view.subviews objectAtIndex:0] setFrame:CGRectMake(0, 0, 320, 480)];
I had this code within the tab's viewControllers.

NOTE - This solution is to just to remove white space left after hiding tab bar.
For hiding tab bar best solution is - #Michael Campsall answer here
The simplest solution to this is to change your view's(in my case its tableView) bottom constraints, instead of giving bottom constraints with BottomLayoutGuide give it with superview. Screenshots attached for reference.
Constraints shown in below screenshots creates the problem, change it according to next screenshot
.
Actual constraints to remove white space should be according to this(below) screenshot.

For those who is still struggling with this. I have found that the problem lays on the constraints. Tab Bar is hidden, yet it already changed my constraint from Storyboard.
SWIFT 3+
self.tabBarController?.tabBar.isHidden = true
let cons = NSLayoutConstraint(item: textview, attribute: NSLayoutAttribute.bottom,
relatedBy: NSLayoutRelation.equal, toItem: self.view,
attribute: NSLayoutAttribute.bottom, multiplier: 1.0, constant: 0)
view.addConstraints([cons])
In my case "textview" was the item, which supposed to fill the white space from hidden TabBar.

Are you sure it's obscured and not just A) not redrawn or B) the frame of your GLView doesn't occupy that space?

some of the superviews of currentViewController.view of the tab bar view controller has clipToBounds set to YES (it's class name is UITransitionView, if not mistaken). To access it use
tabBarController.currentViewController.view.superview.superview.clipToBounds = NO;
after doing this your attempts of resizing a view will not be limited by anything and will succeed. Good luck!

This is just a workaround, but have you tried presenting the graph modally when the user rotates to landscape? This should obscure the tab bar.
You can avoid the transition with
[viewController presentModalViewController:graph animated:NO]

its because the space where tab bar was , not allocated to other views when u set tab bar hidden u can set the corresponding view to stretch or fill the whole screen like scale fill or aspect fill something like that or take a view bigger than the iphine screen so that when u change the phone to landscape it can complete fill the screen

Check the UIView underneath. It may be set to white, so when you hide the tab you're revealing the white UIView. Try setting the UIView to Transparent.

I think u need to set self.navigationController.view.frame to full size ie to UIApplication screen frame before u set tabbar hidden

On after unhiding tababr and reaching to particular view. Tabbar was showing white space on above uitababr. This solved my problem
-(void)viewWillAppear:(BOOL)animated
{
[[self.tabBarController.view.subviews objectAtIndex:0] setFrame:CGRectMake(0, 0, 320, 568)];
}

in the view pushed
- (BOOL)hidesBottomBarWhenPushed
{
return YES;
}

- (void)hidesTabBar:(BOOL)hidden {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0];
for (UIView *view in self.tabBarController.view.subviews) {
if ([view isKindOfClass:[UITabBar class]]) {
if (hidden) {
[view setFrame:CGRectMake(view.frame.origin.x, [UIScreen mainScreen].bounds.size.height, view.frame.size.width , view.frame.size.height)];
} else {
[view setFrame:CGRectMake(view.frame.origin.x, [UIScreen mainScreen].bounds.size.height - 49, view.frame.size.width, view.frame.size.height)];
}
} else {
if([view isKindOfClass:NSClassFromString(#"UITransitionView")]) {
if (hidden) {
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, [UIScreen mainScreen].bounds.size.height)];
} else {
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, [UIScreen mainScreen].bounds.size.height - 49 )];
}
}
}
}
[UIView commitAnimations];
}

My solution: set self.edgesForExtendedLayout = .None in your view controller's viewDidLoad().

I'm assuming that you've already checked the autoresizing arrows on your view?

Have you tried hiding the UITabBar with
tab_bar.hidden = YES

Related

iphone: View on top of UIWebView?

I'm working on a browser app, and I have an address bar on top the UIWebView. On MobileSafari if you scroll down, the address bar starts to move to the top, out of the screen, and the UIWebView doesn't scroll. Only when the address bar disappears completely, it starts to scroll. I would like to have this effect in my app as well.
What's the best way to implement this?
Thanks
The only way to implement this requires iOS 5.
In iOS 5, UIWebView has an UIScrollView subview.
And use the following code:
Set a area for the address bar:
[[myWebView scrollView] setContentInset:UIEdgeInsetsMake(64, 0, 0, 0)];
Move the address bar using the scrollview delegate:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
if(scrollView.contentOffset.y>=-64&&scrollView.contentOffset.y<30)
{
topBar.frame=CGRectMake(0,-44-scrollView.contentOffset.y, 320, 44);
}
else if(scrollView.contentOffset.y<-64)
topBar.frame=CGRectMake(0,20, 320, 44);//Lock the position
}
There is a way, but I am not sure if it is a bit too hacky. First search for the scrollview within the webview, then alter the contentInset and finally add the searchbar(for example) to the scrollview. The following code is just an example, I did not set any frames correctly and 40 is just a made up height for the searchbar. I am not sure if this will work in every iOS Version.
UIWebView * myWebView = [[UIWebView alloc] init]
UISearchBar * mySearchBar = [[UISearchBar alloc] init];
for (NSObject * aSubView in [myWebView subviews]) {
if ([aSubView isKindOfClass:[UIScrollView class]]) {
UIScrollView * theScrollView = (UIScrollView *)aSubView;
theScrollView.contentInset = UIEdgeInsetsMake(40, 0, 0, 0);
[theScrollView addSubview:mySearchBar];
}
}
PeakJi's solution works but is a bit laggy. A better solution would be adding an observer to the UIScrollView's content offset, something like
[scrollview addObserver:self forKeyPath:#"contentOffset"
options:NSKeyValueObservingOptionNew context:nil];
You can find more document on NSKeyValueObserving protocol at
https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html
Come to think of it, it is simply a scrolling view with an address bar stuck on the top, and both the web view and the bar always move together. Now, lets say you create a scroll view and add two subviews, the address bar and the web view (one below the other). It is to be noted that the height of the web view is determined and fixed after the page has been loaded (in webViewDidFinishLoad:).
Hence, it is simply a scrolling view whose contentSize is equal to the height of the bar + the height of the web view. Now, by default the web view allows scrolling, as it has a scroll view as a subview. As only the outer scroll view should be scrolling, it is required that the web view's scrolling be turned off. For that, fetch the first subview (that's the scroll view) and disable its scrolling using:
(UIScrollView*)[myWebView.subviews objectAtIndex:0].scrollEnabled = NO;

Navigation bar and top margin

I have an issue with a UINavigationBar and its y-offset. The bar is displayed without a UINavigationController as superview, yet that should not matter. In the viewController where the navigation bar appears the setup looks like this:
// Add Basic View
CGRect viewFrame = [[UIScreen mainScreen] applicationFrame];
UIView *myView = [[UIView alloc] initWithFrame:viewFrame];
myView.backgroundColor = [UIColor greenColor];
self.view = myView;
[myView release];
UINavigationBar *myBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
.... add some Stuff to the bar...
[self.view addSubview:myBar];
[myBar release];
As I add the navigationBar as a chield View to self.view I assumed that origin.y = 0 would mean that the bar should get directly displayed below the status bar. This works as expected if I start the app on my iPad, rotate it once (or more) and then drill down to the view that is described above. In this case the UINavigationBar is displayed properly. Yet if I start my app and directly drill down to the controller described above (without rotating the device before this particular controller appears) the navigation bar slides 20 points below the status bar. But as soon as I rotate the device then, the bar is fine again. I have checked the viewFrame.origin.y value and it is 20 points in both situations, hence I do not understand why in one case the bar just seems to ignore the origin.y value of its superview but does not in the other.
I am really confused about this, has anybody else ever experienced such an issue?
Thanks a lot for your help!
Ps. I have also tried it with a UIToolbar, the problem is the same.
Yes. My solution is to set the "Full screen on launch" flag to on in Interface Builder for the window in the MainWindow-iPad.xib file. Then design your views as if the 20 pixel status bar were always displayed, so in my root view, I have a toolbar that is positioned 20px below the top of the screen in the content view.

how to show the tabbar when keyboard appears in iphone

hello all i am working in a tabbar based application where i need to show a keyboard , the keyboard appearing generally but I want my tabbar should be shown and on above of the tabbar only the keyboard should shown how this can be done..
thank you all
You can move the tabbar along with the keyboard like this:
- (IBAction)textBoxEditing:(id)sender {
CGRect frame = [[[self tabBarController] tabBar] frame];
frame.origin.y = 712;
[UIView animateWithDuration:0.25f animations:^
{
[[[self tabBarController] tabBar] setFrame:frame];
}];
}
The example above is for iPad in portrait. 712 is the original position of the tabbar(975) minus the height of the keyboard(264).
Read More
This is impossible. The keyboard always appears at the bottom of the screen.
If the tabbar is needed while the keyboard is visible you could only move the tabbar above the keyboard, or resize the tabbarcontroller, so that the tabbar remains visible.
Are you shure you need the tabbar while the keyboard is visible? Remember a tabbar is for changing the view. Perhaps you need to rethink your interaction design.

Resizing UINavigationBar on rotation

I have a subclass of UIViewController which handles a UIView. The viewcontroller is presented modally (it slides up from the bottom of the screen). At the top of the view, i have added a navigation bar. Note that this bar is not handled by a navigation controller.
I want to get the navbar to shrink in height when the view rotates to landscape (similar to how it behaves when it is handled by a UINavigationController). However, I can't set its autoresizing mask to flexible height in IB, and doing so in code causes the navbar to disappear completely.
Is there a way to do this? How is it done by the UINavigationController?
P.S. I would prefer not having to resort to a scaling transform, since this would mess up the text in the title.
EDIT: I solved it with a little help, read the answer posted below.
Rather than set it's autoresizing mask, why don't you just check the current orientation in viewWillAppear, as well as in didRotateFromInterfaceOrientation, and set the appropriate frame?
- (void) updateNavBar {
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if ((UIInterfaceOrientationLandscapeLeft == orientation) ||
(UIInterfaceOrientationLandscapeRight == orientation)) {
myNavBar.frame = CGRectMake(0, 0, 480, 34);
} else {
myNavBar.frame = CGRectMake(0, 0, 320, 44);
}
}
- (void) viewWillAppear {
[self updateNavBar];
// ... SNIP ...
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[self updateNavBar];
// ... SNIP ...
}
I found the solution, and in hindsight i feel rather stupid. I just had to include flexible bottom margin in the navbar's autoresize mask. Credit is due to user RayNewbie in this thread, which pointed me to the solution:
http://discussions.apple.com/thread.jspa?messageID=8295525

Rotation affecting Navigation Bar unpredictably

Here is my setup: one navigation controller, two views
The first view, the rootview, displays the statusbar and navigation bar (portrait view).
When the rootviewController senses rotation, it hides the nav bar and status bar and then it pushes view 2 onto the navigation controller (in landscape now).
This part works as expected.
When View2 viewcontroller senses rotation (back to portrait), it pops itself of the navigation controller, revealing view 1. View 1 then unhides the status bar and nav bar.
From here, it gets weird. Depending on when I unhide the navigation bar, I get strange results. As you can see below (The beaker photo should be just below the navbar at the top of the screen).
I have tried unhiding the navigation bar in:
viewWillRotate/viewDidRotate of view 2
viewWillAppear/viewDidAppear of view 1
poptoRootView in the navigation controller (I subclassed just to try)
Nothing works. Any Idea what is going on? This should be simple, but maybe I am doing things in the wrong places.
Check your autoresizing mask on all views in your nib and make sure its all set properly. If you have anything the way its not supposed to be it will freak out on rotation.
Not sure why it's necessary, but when you're swaping views, you must apply a transformation to your view (with only 1 view the iPhone does this for you), and you must set the bounds of it.
Here is the code that should work for you (on the willAnimateFirstHalfOfRotationToInterfaceOrientation):
#define degreesToRadians(x) (M_PI * (x) / 180.0)
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
self.view = landscapeView;
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(90));
self.view.bounds = CGRectMake(0.0, 0.0, 480.0, 320);
} else {
self.view = portraitView;
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(0));
self.view.bounds = CGRectMake(0.0, 0.0, 300, 480);
}
In the end, I reworked my app. (to use a modal view controller)
But I came into similar issues, instead white space where the status bar was located.
I think both problems can be attributed to not talking to the Navigation Controller when rotating/resizing views (instead I was talking to the ViewController.
For details of how I solved the problem:
iPhone + CGAffineTransFormRotate(pi/2) + statusBarHidden:YES + presentModalViewController = 20 pixels of white space