I have added a custom titleView to my UINavigationItem, and that contains a view that is intended to be under the status bar. It looks fine, and when I push another viewcontroller and that transitions away in the standard right-to-left animation it looks fine. However, when I [self.navigationController popViewControllerAnimated:YES] it clips the top of this view until the animation is finished. Please see attached image for a better explanation of the problem.
It's only until after the pop-animation is done that it looks normal again. I have tried everything I can think of. Setting cropsToBounds to NO on all the views the viewController AND navigationBar. I've tried also layer.masksToBounds and just about every property that sounds familiar. I've added a timer that prints the frame rectangle of the navigationBar and the custom titleView and it doesn't appear that they change anything.
Does anybody know what I'm doing wrong?
Two ways to do it :
if ([self respondsToSelector:#selector(setEdgesForExtendedLayout:)]) { // if iOS 7
self.edgesForExtendedLayout = UIRectEdgeNone; //layout adjustements
}
Or
You need to set Delta of your view controller. Switch Story board to ios6.1 or later from utility area (1st item). Then select view of your Vc and in size inspector menu in utility area there will be delta section below frame. There will be triangle before every delta. Triangle y to 64 (you should be on ios6.1 or later of your storyboard).
If you need help on Deltas visit : Interface Builder: What are the UIView's Layout iOS 6/7 Deltas for?
Related
I just create a new project template for TabBar application in Xcode.
I arrange a storyboard to let a UITabbarController embedded in another view controller like this (in order to provide red header for all tab pages)
Notice that in first tab page, I put two labels on the first page. Both are locating at the top and bottom of the screen.
and here is a setting of first tab view controller.
and this is the result i have got on both device and simulator.
Why and how can my second label half shown?
i try to uncheck all options and setting
self.automaticallyAdjustsScrollViewInsets = NO;
self.edgesForExtendedLayout = UIRectEdgeNone;
but none is working.
How can I solve this?
Thanks.
UPDATE
I already know what is the culprit behind this. It is the tabbar's height for ipad landscape mode normally the height is 49 but according to apple here
They said the height will be 56 for ipad.
But in interface builder, it is always 49 and and the rootviews of my viewcontroller in each tab are calculate using this 49 height of tabbar even though i use an autolayout.
So I have a way to overcome this by create another view and let it has smaller height by 7 pixel from rootview.
But WHY interface builder display 49 pixel of tabbar instead of 56?
It is not quite clear to me what you are really asking, but if you simply want a red header at the top of your view controllers, you can embed them inside of an UINavigationController. Even if you still want a UITabBarController, embed every child view inside of a UINavigationController and then you can control the look of your header.
(Note: I would just add this as a comment but I don't have the reputation.)
I am designing a screen using IB and in design time this is how the screen looks like:
I am using auto layout and there are no missing constraints. This is how it lookes like when I run it using the simulator:
Its a sit it has no idea there is a opaque top bar there and starts layouting the views directly from the top.
does anyone has any idea why this is happening?
Thanks
The size, status bar, orientation, top bar, bottom bar are only simulated at the attributes inspector , e.i. What u see, is NOT what u get, it's just simulate...
To make status bar/bottom bar/orientation etc. U must do it via code or .xib attributes inspector/size inspector.
For status bar, u can see this.
Hope it's help.
Add the following code to viewDidLoad in you view controller:
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
You can achieve this by implementing a new property called edgesForExtendedLayout in iOS7 SDK. Please add the following code to achieve this,
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
You need to add the above in your -(void)viewDidLoad method.
iOS 7 brings several changes to how you layout and customize the appearance of your UI. The changes in view-controller layout, tint color, and font affect all the UIKit objects in your app. In addition, enhancements to gesture recognizer APIs give you finer grained control over gesture interactions.
Using View Controllers
In iOS 7, view controllers use full-screen layout. At the same time, iOS 7 gives you more granular control over the way a view controller lays out its views. In particular, the concept of full-screen layout has been refined to let a view controller specify the layout of each edge of its view.
The wantsFullScreenLayout view controller property is deprecated in iOS 7. If you currently specify wantsFullScreenLayout = NO, the view controller may display its content at an unexpected screen location when it runs in iOS 7.
To adjust how a view controller lays out its views, UIViewController provides the following properties:
edgesForExtendedLayout
The edgesForExtendedLayout property uses the UIRectEdge type, which specifies each of a rectangle’s four edges, in addition to specifying none and all. Use edgesForExtendedLayout to specify which edges of a view should be extended, regardless of bar translucency. By default, the value of this property is UIRectEdgeAll.
extendedLayoutIncludesOpaqueBars
If your design uses opaque bars, refine edgesForExtendedLayout by also setting the extendedLayoutIncludesOpaqueBars property to NO. (The default value of extendedLayoutIncludesOpaqueBars is NO.)
automaticallyAdjustsScrollViewInsets
If you don’t want a scroll view’s content insets to be automatically adjusted, set automaticallyAdjustsScrollViewInsets to NO. (The default value of automaticallyAdjustsScrollViewInsets is YES.)
topLayoutGuide, bottomLayoutGuide
The topLayoutGuide and bottomLayoutGuide properties indicate the location of the top or bottom bar edges in a view controller’s view. If bars should overlap the top or bottom of a view, you can use Interface Builder to position the view relative to the bar by creating constraints to the bottom of topLayoutGuide or to the top of bottomLayoutGuide. (If no bars should overlap the view, the bottom of topLayoutGuide is the same as the top of the view and the top of bottomLayoutGuide is the same as the bottom of the view.) Both properties are lazily created when requested.
I have a UIViewController, MyViewController, with a UIToolbar at the top. Using interface builder the doc outline looks like this:
View
- subview1
- subview2
- UIToolbar
- Bar Button Item1
- Bar Button Item2
- Bar Button Item3
MyViewController is used throughout my app. Sometimes it's in a UINavigationcontroller, other times it's in a UIPopoverView.
When it appears in UINavigationController, the navigation bar covers up the UIToolbar and all other content near the top of View. In this screenshot you can see that the UIToolbar is completely covered up, and UIButton w/ an image of a green light bulb is partially covered.
According to the apple documentation
Any view that needs to be anchored to the top and just below the status bar (i.e. UIToolbar, UIButton, etc.) requires additional work for proper placement.
It proceeds to give a solution that simply uses constraints to move your VC's content down by x pixels, in my case the UIToolbar. This doesn't seem like a good solution because it assumes you always want the content moved down below the nav bar. In my case, I obviously don't since MyViewController is not always in a UINavigationController. When I use the constraint solution provided in these docs, the UIToolbar is oddly floating down x pixels unanchored from the top in all cases where MyViewController is not in a UINavigationController.
Am I missing something with how I am supposed to display a VC's content within a UINavigationController? Thanks so much.
In iOS7, UINavigationBar has translucent property and views of child VCs of UINavigationViewController are underneath UINavigationBar by default.
If you don't need this translucent effect, turn off this property by using the following code.
self.navigationController.navigationBar.translucent = NO
You can also use #ldindu's way as well.
If you are running on iOS 7.0 version then you need to set following property which is newly introduced in iOS 7.0 as follows
self.edgesForExtendedLayout = UIRectEdgeNone;
as by default edgesForExtendedLayout property is set to UIRectEdgeAll that means the view controllers use full-screen layout by default.
Identify whether you are using iOS 7.
#define IS_IOS7 [[[UIDevice currentDevice] systemVersion] hasPrefix:#"7"];
- (float)topPadding
{
return (IS_IOS7) ? 20.0f : 0.0f;
}
Use increment the Y axis of the frame by [self topPadding] to move it further down.
I hope your problem is solved.
If written in Swift, it's edgesForExtendedLayout = UIRectEdge()
I have a test project and created ViewController which is embedded in TabBarController. I've placed 'UISearchBar' and 'UISegmentedControl' with constraints and in portrait mode they are clickable. But when I rotate to landscape mode(iPhone) only 320 pixels of the searchBar and segmentedControl is clickable, the rest isn't. This is better explained in the figures below.
Why is this happening?
How should I "stretch" the clickable area in landscape mode?
As you can see the constraints are working fine, the components have their correct sizes.
Some of your constraints are working fine, but very likely others are not. If the segmented control is only partially tappable in landscape, you should check the frame sizes for it's superview(s).
It looks like in landscape mode the segmented control is partially outside the superview frame. If the superview frame is ok, look further into the superview hierarchy.
To fix it, try this:
Select all the components in IB (search bar + segmented control + date picker)
Open menu 'Editor' -> 'Resolve Auto Layout Issues' -> 'Reset to Suggested Constraints'
I've just put the following code in mine TabBarViewController class.
- (void)viewDidLayoutSubviews
{
// fix for iOS7 bug in UITabBarController
self.selectedViewController.view.superview.frame = self.view.bounds;
}
I have a strange one that I can not seem to fix. I am currently working on updating my app to iOS7. This all worked in iOS6. It is an universal app and thus uses same xib files. However the iPad uses UISplitViews on some. Like I said, this all worked in iOS6 oh this all works on the iPhone too.
The problem is a grey bar at the bottom. I changed the tab bar to be opaque to move views up properly as i had some UI clipped to bottom of views and that went underneath the tab bar, sidetracked there. But if i set it back to translucent bar, it goes underneath but stretched properly. if i dont, it adds a bar. Other tabs work fine when NOT using splitview.
The UISplitviewController is added programmatically.
See attached image for better description.
This I have tried:
Added autoresize on splitview
Checked xib for subviews in the splitviews to have auto resize
Tried to force splitview to be screen bounds
Removed clips to bounds on all views
Removed autoresize subviews
Any ideas would be welcomed.
Thank you all.
UPDATE:
setting the background colour the uisplitview, it does colour the bar black. So the uisplitview is definitely stretching to it.
I subclassed UISplitViewController and added the line below to viewDidLoad and that fixed the grey line.
self.extendedLayoutIncludesOpaqueBars = YES;
I believe I have found an alternative solution for you. I have had the exact same problem, mostly because we are both doing something against Apple's Guidelines which is having a SplitViewController nested within a Tabbar controller (SplitView should be the root view). This was okay in iOS 5/6, but now in iOS 7 there are far too many side effects to achieve this.
The reason you see your view stretch completely when you set the bar to be translucent is because the bar is NOT taken into account when drawing the view. When you set translucent to false, it is then taken into account of the view and you will see that grey bar there because that's your view pretending there's a tabbar at the bottom of the screen.
And as always, a SplitViewcontroller's height cannot be changed, as it is determined by the visible window height.
I tried everything you did and then some. The real solution came from using a third-party Split View Controller.
I recommend switching over to https://github.com/mattgemmell/MGSplitViewController . This split view controller is actually one large View with container views living inside of it. Because of this, you avoid all the side effects of putting an actual split view controller within a tab bar.
If that doesn't float your boat, you could create your own solution which follows the same idea of having one UIViewController with two container views contained in it, though the people behind MGSplitViewController did a good job of that already.
This was the only way I was able to solve this issue, let me know if you find an alternative.
Instead of creating a subclass for UISplitViewController, I just added this code on my master's viewDidLoad:
self.splitViewController?.extendedLayoutIncludesOpaqueBars = true
For the controller that is the detail view of UISplitViewController you just do this:
-(UITabBarController*)tabBarController{
return nil;
}