I have setup AdMob in my ViewController and it's positioned at the bottom. Everything is good until I hide my navigation bar. The AdMob frame goes up when my navigation bar is hidden. How can I make it stick to the bottom of my view? Here's what I have
-(void)navBarTransition:(BOOL)hide
{
[[self navigationController] setNavigationBarHidden:hide animated:YES];
//addjust frame height when ads is visible
if(hide)
{
CGRect frame = CGRectMake(0.0,self.view.frame.size.height + GAD_SIZE_320x50.height,GAD_SIZE_320x50.width, GAD_SIZE_320x50.height);
[bannerView_ setFrame:frame];
}
}
Just before hiding the navigation bar, move the origin.y down by the height of it. Also ensure you have no autosizing masks (flexible top/bottom margins?) interfering with your positioning.
CGRect bFrame = bannerView_.frame;
CGFloat newY = bFrame.origin.y + self.navigationController.navigationBar.frame.size.height;
bFrame.origin.y = newY;
[bannerView_ setFrame:bFrame];
If this doesn't work you could try using CJPAdController (Disclosure: I wrote this class). If you implement this class, you can simply adjust your code to the following (have just tested and it appeared to work as you would like it to):
[[self navigationController] setNavigationBarHidden:hide animated:YES];
if(hide)
[CJPAdController sharedManager] fixAdViewAfterRotation];
Related
iOS Developers will surely knows about the issue about status bar and the famous "slide/hamburger/drawer". The issue is well explained here: http://uxmag.com/articles/adapting-ui-to-ios-7-the-side-menu
I'm using MMDrawerController library and it has a nice hack that lets us to create a dummy status bar just above the container view controller. Unfortunately this doesn't work really good. What's the news? The news is that I stumbled upon an app (Tinder) that perfectly solve this mind blowing issue. I've created a gif that perfectly shows what Tinder does.
You need to wait a few seconds for seeing the gif because there's a bug in it and I don't know how to get rid of. Just wait one/two seconds and you will able to see the gif correctly.
Anyway, what Tinder does? When the user taps on the top left menu button and begin to swipe right the status bar fades out neatly. And when the view is revert to the original position the status bar will show up again.
I am both happy and a bit sad for this because this means that a way must be to do it but I really don't know how to implement it (perhaps hacking MMDrawerController). Any help will be so much appreciated.
IMPORTANT
Please pay attention to the fact that the method setStatusBarHidden: will completely hide the status bar, this means that the entire view is with a height -20px. This is obviously not the solution because as you can see from the gif the view is not stretched.
Your main problem is with MMDrawerController. If you'll digg into it you'll find a lot of methods statusbar related such as setShowsStatusBarBackgroundView setStatusBarViewBackgroundColor and more. Something in their code pushes the view up when the statusbar is hidden.
Alternatively you can use another drawer controller or use custom code.
Here's a simple way how to accomplishe this:
ViewControllerA:
-(BOOL)prefersStatusBarHidden
{
return _hidden;
}
- (void)statusHide
{
[UIView animateWithDuration:0.4 animations:^() {[self setNeedsStatusBarAppearanceUpdate];
}completion:^(BOOL finished){}];
}
ViewControllerB: (Container in ViewControllerA)
- (IBAction)move:(UIButton *)sender
{
parent = (ViewController*)self.parentViewController;
parent.hidden = !parent.hidden;
CGRect frame = parent.blueContainer.frame;
if(parent.hidden)
{
frame.origin.x = 150;
}
else
{
frame.origin.x = 0;
}
[UIView animateWithDuration:1 animations:^() {parent.blueContainer.frame = frame;}completion:^(BOOL finished){}];
[parent statusHide];
}
For iOS 6 compatieblty use:
[[UIApplication sharedApplication] setStatusBarHidden:_hidden withAnimation:UIStatusBarAnimationFade];
The table view and other subviews will stay in their location and won't be pushed up.
Edit:
Adding a NavigationBar:
UINavigationController will alter the height of its UINavigationBar to
either 44 points or 64 points, depending on a rather strange and
undocumented set of constraints. If the UINavigationController detects
that the top of its view’s frame is visually contiguous with its
UIWindow’s top, then it draws its navigation bar with a height of 64
points. If its view’s top is not contiguous with the UIWindow’s top
(even if off by only one point), then it draws its navigation bar in
the “traditional” way with a height of 44 points. This logic is
performed by UINavigationController even if it is several children
down inside the view controller hierarchy of your application. There
is no way to prevent this behavior.
Taken from here
You could very simply subclass UINavigationController and create your own navbar to avoid this annoyness.
i don't know if it will sove your problem but i got almost the same effect using the SWRevealViewController project. In the appDelegate I've set the delegate method from this class to do this:
- (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position {
#ifdef DEBUG
NSArray *teste = #[#"FrontViewPositionLeftSideMostRemoved",#"FrontViewPositionLeftSideMost",#"FrontViewPositionLeftSide",#"FrontViewPositionLeft",#"FrontViewPositionRight",#"FrontViewPositionRightMost",#"FrontViewPositionRightMostRemoved"];
NSLog(#"%# %d", teste[position], position);
#endif
if (position == FrontViewPositionRight)
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
UINavigationController *frontViewController = (id)revealController.frontViewController;
frontViewController.navigationBar.centerY += (position == FrontViewPositionRight) ? 20 : 0; // 20 == statusbar heihgt
}
- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position {
if (position == FrontViewPositionLeft)
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
}
centerY is a category in the UIView which sets the center.y without dealing the boring part of setting frame variables.
Here is how you should do that in iOS 7:
#implementation ViewController
{
BOOL _hideStatusBar;
}
-(UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleDefault;
}
-(UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
return UIStatusBarAnimationFade;
}
-(BOOL)prefersStatusBarHidden
{
return _hideStatusBar;
}
-(void)setStatusBarHidden:(BOOL)hidden
{
[UIView animateWithDuration:1.0 animations:^{
_hideStatusBar = hidden;
[self setNeedsStatusBarAppearanceUpdate];
}];
}
#end
Check out the method setStatusBarHidden:withAnimation: on UIApplication. It will allow you to show or hide the status bar and the animation can be none, fade, or slide. You just need to add a call to hide the bar and one to show the bar at the correct times and decide if you like the fade as you illustrated or if the slide works better for you.
https://developer.apple.com/library/ios/DOCUMENTATION/UIKit/Reference/UIApplication_Class/Reference/Reference.html#//apple_ref/occ/instm/UIApplication/setStatusBarHidden:withAnimation:
You can used -setStatusBarHidden:withAnimation: if you adjust your views frame in -viewDidAppear:, then you will not see any stretch.
Note that autolayout is disabled.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect frame = self.view.frame;
// adjust root view frame
frame.origin.y -= 20;
frame.size.height += 20;
[self.view setFrame:frame];
// adjust subviews y position
for (UIView *subview in [self.view subviews])
{
CGRect frame = subview.frame;
frame.origin.y += 20;
[subview setFrame:frame];
}
}
- (IBAction)sliderChanged:(id)sender
{
UISlider *s = (UISlider *)sender;
if (s.value > .5)
{
UIApplication *app = [UIApplication sharedApplication];
if (![app isStatusBarHidden])
[app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
}
else
{
UIApplication *app = [UIApplication sharedApplication];
if ([app isStatusBarHidden])
[app setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
}
}
I have an application like the photos app where the main view is a UIScrollView which takes up the full size of the screen. Also, like the photos app, when the user taps the screen there are translucent navigation, status, and tool bars which reappear / disappear.
I am having a problem setting the UIViewControllers main view as a UIScrollView and having it take up the full length of the screen. The problem is that when the navigation and status bars are shown, the UIScrollView gets pushed down by the height of the navigation and status bars (it doesn't go underneath them like it's suppose to). When the user taps the screen and the navigation / status bars disappear, then it resets itself to take up the full length of the screen like it's suppose to.
A simple work around of setting the main view as a UIView and attaching a UIScrollView on top of it works. However, I'd like to try and get this to work without any workarounds (ie adjusting the UIScrollViews contentInset, etc) because in theory it should work.
Below is the code I'm implementing:
- (void)loadView
{
self.wantsFullScreenLayout = YES;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame: CGRectMake(0,0,320,480)];
scrollView.contentSize = CGSizeMake(320, 480);
scrollView.scrollEnabled = NO;
scrollView.contentOffset = CGPointZero;
scrollView.bounces = NO;
self.view = scrollView;
[scrollView release];
}
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.navigationBar.translucent = YES;
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackTranslucent animated: NO];
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.barStyle = UIBarStyleBlack;
self.navigationController.toolbar.translucent = YES;
[self startTimer];
}
- (void) viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.navigationController.navigationBar.translucent = NO;
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleDefault animated: NO];
[self cancelTimer];
}
UPDATE: I've noticed it's the contentOffset and contentInset that are changing, not the scrollViews frame. When the bars have disappeared and the UIScrollView is the full size of the screen (as it should be), the contentOffset and contentInset are as follows:
Content Offset: {0, -20}
Content Inset: {20, 0, 44, 0}
When the bars are visible and the UIScrollView is pushed down, the contentOffset and contentInset are as follows:
Content Offset: {0, -64}
Content Inset: {64, 0, 44, 0}
I solved a similar issue on iOS7 after reading Apple's UI Transition Guide:
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/TransitionGuide/AppearanceCustomization.html
It turns out UIViewController has a automaticallyAdjustsScrollViewInsets boolean property.
Default is true, disabling this made my UIScrollView fill up the entire window, instead of being pushed down.
I spoke with DTS about this and they said this is the designed behavior and recommended to attach the UIScrollView to a parent UIView.
Try be setting:
self.view.frame = CGRectMake(0.f, -44.f, 320.f 480.f);
It may not size as you wish, but you can adjust it...
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;
I'm trying to display transparent UINavigationBar on top of Scrollview.
This is actual result of code that I have written...
where as I'm expecting view to be displayed like below image, which happens after I slightly scroll the image.
Code :
- (void) loadView {
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView.pagingEnabled = YES;
pagingScrollView.backgroundColor = [UIColor blackColor];
pagingScrollView.showsVerticalScrollIndicator = NO;
pagingScrollView.showsHorizontalScrollIndicator = NO;
pagingScrollView.contentSize = CGSizeMake(pagingScrollViewFrame.size.width * [self imageCount],
pagingScrollViewFrame.size.height);
pagingScrollView.delegate = self;
self.wantsFullScreenLayout = YES;
pagingScrollView.scrollsToTop = YES;
self.view = pagingScrollView;
}
question is how do I make view to load as I expected without user interacting to it?
any suggestion or help is appreciated..
EDIT: I'm creating view totally from CODE
It seems like you're trying to do this in code not in the IB. If so, you have to put your code in the viewDidLoad of the Application Delegate (e.g. MyProgramAppDeligate class or whatever). If you want it in some certain views, put it in the viewDidLoad of the UINavigationController class/subclass.
Does this satisfy your requirement?
self.navigationController.navigationBar.translucent = YES;
self.navigationController.navigationBar.tintColor = [UIColor blackColor];
And to make your statusbar translucent.
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:YES];
[self setWantsFullScreenLayout:YES];
I have this inside my willWillAppear and I reset it in my viewWillDisappear.
You have to set
self.navigationController.navigationBar.translucent = YES;
As soon as you do this, the 0,0 coordinate is behind your navigation bar not below it and your view shifts behind the bar.
It may be a conflict between IB and your code. I would add the line of code suggested by Ortwin in the viewDidLoad method and then double check you've set the navBar to translucent in IB.
The code you have posted has nothing to do with the opacity of the navigation bar. Show where you are setting the configuration of the components of the view. There you could just set the alpha of the navigation bar. Alternatively if you are using nibs, just set the alpha in IB.
Since you say that it works fine after the user (you) slightly scrolls the image, the problem might be that the UINavigationBar's drawRect: method does not get called after the UIScrollView is loaded.
Suggestion: Can you explicitly call setNeedsDisplay on the navigation bar after the view is loaded?
Have you tried setting the frame of the scroll view with an Y origin of 0 after setting the nav bar to transparent?
EDIT: I mean, you don't say what's the frame used in your code.
In viewDidLoad, try moving the origin up 32 pixels and grow the height by 32 pixels as well:
pagingScrollView.frame = CGRectMake(pagingScrollView.frame.origin.x, pagingScrollView.frame.origin.y-32, pagingScrollView.frame.size.width, pagingScrollView.frame.size.height+32);
In viewWillAppear scroll the content to the correct location.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIScrollView *scrollView = (UIScrollView *)self.view;
[scrollView setContentSize:CGSizeMake(320,568)];
[scrollView scrollRectToVisible:CGRectMake(0, 548, 320, 20) animated:NO];
}
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.