UIToolbar goes under status bar in iOS7 - objective-c

I have a UIView and I have a UIToolbar and UIWebView.
I want to show toolbar at top of UIView and after that the rest of page covered with webView.
But toolbar goes under status bar like this
How can I correct it in iOS7.

1) Set the toolbar Y position to 20 (in the interface builder or in the code)
2) Set the toolbar delegate
3) In your toolbar delegate implement:
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}

Set up toolbar delegate to your view controller and implement method:
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar {
return UIBarPositionTopAttached;
}

The only correct solution in 2k17 is to attach your toolbar/navigationBar to leading/trailing of your superview, top to topLayoutGuideBottom and to implement positionForBar:. This will produce correct result on all devices.

Related

UISearchBar Disappears After Events

I have a UISearchBar in my view contained inside a UITableView above the top-most cell. Everything works fine until I push a new view controller onto the navigation stack. Once I pop the new VC and return to the original view controller the search bar does not show atop the table. Instead there is a white space between my navigation bar and the top row of my table view. However, if I click this white space then the search bar opens as if it were there normally, and when I click cancel again all is well.
I think that somehow the view for the UISearchBar is being set to be entirely white, but I have no idea why. I originally have the UISearchBar just added into the storyboard, as part of a UISearchDisplayController. How can I prevent the search bar from going white after my VC is unwound to from another controller than was pushed onto the navigation stack?
I have the same problem. I don't think it relates to the color of the search bar but to the layout of the search bar's subviews. After many trials and errors I came up with this solution:
#interface MySearchBar : UISearchBar
#end
#implementation MySearchBar
-(void) layoutSubviews
{
[super layoutSubviews];
if (self.subviews.count == 1)
{
UIView *subview = [self.subviews objectAtIndex:0];
subview.frame = self.bounds;
}
}
#end
Use MySearchBar instead of UISearchBar

Hide statusbar with UINavigationBar barPositionTopAttached

I have rootViewController - UINavigationController.
As you know UINavigationController has UINavigationBar.
In iOS 7 UINavigationBar could be with barPosition topAttached.
I want to hide ON/OFF statusBar by clicking on button. But I also want that UINavigationBar should be always barPositionTopAttached.
- (BOOL)prefersStatusBarHidden {
return __statusBarHidden;
}
- (IBAction)tapShowPhotosButton:(id)sender {
__statusBarHidden = !__statusBarHidden;
[self setNeedsStatusBarAppearanceUpdate];
}
For now UINavigationBar changed barPosition from topAttached to top, and so on.
Try this:
- (IBAction)tapShowPhotosButton:(id)sender
{
__statusBarHidden = !__statusBarHidden;
[[UIApplication sharedApplication] setStatusBarHidden:__statusBarHidden withAnimation:UIStatusBarAnimationSlide];
[self setNeedsStatusBarAppearanceUpdate];
}
The Navigation Bar should automatically move with the status bar
I write to technical support and get next answer:
As stated in the documentation for , -positionForBar is called when the bar needs to know its position in its new window. It will not be called when the status bar hides or unhides. The navigation controller handles resizing the navigation bar in response to a status bar change. Unfortunately, UINavigationController does not provide any API to customize the navigation bar resizing behavior.

How to hide the NavigationBar when i use SWRevealViewController embed in UINavigationController?

When i use SWRevealViewController as initial view or not embedded in UINavigationController the result is as i expected:
but when the SWRevealViewController comes from UINavigationController tee result is:
How can i avoid the NavigationBar presented in the Rear view?
Please add the following code to the viewWillAppear: method of the viewcontroller whose navigation bar you need to hide.
[super viewWillAppear:YES];
[self.navigationController.navigationBar setHidden:YES];
[self.navigationController.navigationBar.backItem setHidesBackButton:YES];
Try, this code for rear view controller
- (void)viewWillAppear:(BOOL)animated
{
self.navigationController.navigationBar.hidden = YES;
}
If you really need Navigation Controller on top of SWRevealViewController:
You got to hide navigation bar from navigation controller of your SWRevealViewController.
U can do this in IB (assuming you are using Storyboards):
Select Navigation Controller in your Storyboard
Open Attributes inspector
Find section "Navigation Controller", uncheck "Shows Navigation Bar"
Next, If you want navigation bard in front view controller, then attach it to separate Navigation Controller. You will have two Navigation Controllers, think on which one you want to push - it will have different effect.

iOS7 - Setting selectedIndex of UITabBarController breaks touch events along right-hand edge of screen?

I've hit a weird problem with UITabBarController on iOS7 and can't seem to find a workaround, so any help would be welcome!
Scenario:
Navigation-based app using landscape orientation on iPad.
App consists of a main view, and a second view which is a UITabBarController.
TabBarController has two tabs.
First view has two buttons - each button performs a segue to the tab bar controller and sets a different tab as selected. (i.e. button1 selects the first tab, and button2 selects the second tab).
Setting the tab is done in prepareForSegue by calling setSelectedIndex on the tab bar controller.
Outcome:
On iOS 7 I am finding that the view shown in the tab bar controller fails to register any touch events along the right-hand edge of the view! So in the storyboard shown above, the UISwitch on the right side of the screen cannot be tapped.
I've even attached a tap gesture recognizer to the views and used it to log the area of the screen that can be touched - it seems to register touch events up to about x=770 points across. The remaining 1/4 of the screen is 'untouchable'!
After the segue, if you manually switch to the other tab and switch back again, the touch events are 'fixed' and the full view responds to touches again.
This doesn't seem to be a problem on iOS 5 / 6.
Any help much appreciated as to:
What is causing this to happen in the first place (iOS7 bug / change?)
How else can I work around this? I've tried calling setSelectedViewController as well as using setSelectedIndex and this seems to be the same.
Thanks in advance.
I ended up raising this with Developer Tech Support, and it looks like a bug. This is the response I got back from Apple:
The container view that the tab bar controller sets up to contain your view controller is not being resized to account for the interface being in landscape orientation. It's dimensions at the time your view controller is displayed are 768 (width) x 1024 (height).
The view hierarchy looks like this when the selected tab's view is displayed:
UIWindow
/* Navigation Controller */
UILayoutContainerView
UINavigationTransitionView
UIViewControllerWrapperView
/* Tab bar controller */
UILayoutContainerView
UITransitionView
UIViewControllerWrapperView <-- Incorrectly sized.
/* MyViewController */
MyViewController.view
The incorrect size of UIViewControllerWrapperView does not cause a display problem because subviews are still displayed even if they are outside their superview's bounds. However, event routing is much more strict. Events on the right quarter of the screen are never routed to your view controller's view because the hit test fails at the wrongly-sized UIViewControllerWrapperView where the event falls outside UIViewControllerWrapperView's bounds.
As a workaround, I subclassed UITabBarController, and added the following in viewWillAppear:
#implementation FixedIOS7TabBarController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Fix the frame of the UIViewControllerWrapperView
self.selectedViewController.view.superview.frame = self.view.bounds;
}
#end
Hope that helps someone else....
As explained in this answer,
The container view that the tab bar controller sets up to contain your
view controller is not being resized to account for the interface
being in landscape orientation. Its dimensions at the time your view
controller is displayed are 768 (width) x 1024 (height).
I was encountering this problem when the TabBarController was originally displayed in portrait mode. When the device was rotated into landscape mode, the view was unresponsive on the right hand side.
The solution proposed in that answer did not work for me, because viewWillAppear: is invoked only once. However, viewDidLayoutSubvews is invoked whenever the view changes, including rotations, so my solution was to subclass UITabBarController and perform the workaround in viewDidLayoutSubvews:
#implementation FixedIOS7TabBarController
- (void)viewDidLayoutSubviews
{
// fix for iOS7 bug in UITabBarController
self.selectedViewController.view.superview.frame = self.view.bounds;
}
#end
End up finding a workaround here:
self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Right answer don't worked for me, cause user can change orientation; And it still not touchable in some area when change orientation.
So I create my own solution, I don't sure that is normal solution.
#implementation FixedIOS7TabBarController
- (UIView*)findInSubview:(UIView*)view className:(NSString*)className
{
for(UIView* v in view.subviews){
if([NSStringFromClass(v.class) isEqualToString:className])
return v;
UIView* finded = [self findInSubview:v className:className];
if(finded)
return finded;
}
return nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIView* wraperView = [self findInSubview:self.view className:#"UIViewControllerWrapperView"];
wraperView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
#end
Works perfectly for me!
In the list of view controllers on the left hand side navigate to the views/view controllers affected, drag the view to underneath the first responder so that it is disassociated to the view controller's view.
Then go to the layout tab on the right hand side, select all 4 anchors and both sets of resizing arrows (horizontal + vertical).
Then drag the view back to where it was originally (just below the view controller).

How to change status bar color in iOS7? [duplicate]

My application has a dark background, but in iOS 7 the status bar became transparent. So I can't see anything there, only the green battery indicator in the corner. How can I change the status bar text color to white like it is on the home screen?
Set the UIViewControllerBasedStatusBarAppearance to YES in the .plist file.
In the viewDidLoad do a [self setNeedsStatusBarAppearanceUpdate];
Add the following method:
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
Note: This does not work for controllers inside UINavigationController, please see Tyson's comment below :)
Swift 3 - This will work controllers inside UINavigationController. Add this code inside your controller.
// Preferred status bar style lightContent to use on dark background.
// Swift 3
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
Swift 5 and SwiftUI
For SwiftUI create a new swift file called HostingController.swift
import Foundation
import UIKit
import SwiftUI
class HostingController: UIHostingController<ContentView> {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
Then change the following lines of code in the SceneDelegate.swift
window.rootViewController = UIHostingController(rootView: ContentView())
to
window.rootViewController = HostingController(rootView: ContentView())
Alternatively, you can opt out of the view-controller based status bar appearance:
Set View controller-based status bar appearance to NO in your Info.plist.
Call [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
Note: This method has been deprecated in iOS9. Use preferredStatusBarStyle on the UIViewController instead. (see Apple Developer Library)
You can do this without writing any line of code!
Do the following to make the status bar text color white through the whole app
On you project plist file:
Status bar style: Transparent black style (alpha of 0.5)
View controller-based status bar appearance: NO
Status bar is initially hidden: NO
Note: The most upvoted answer does not work for iOS 7 / 8
In Info.plist set 'View controller-based status bar appearance' as NO
In AppDelegate add
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
to
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
...
}
This solution works for iOS 7 / 8.
For me, nothing happened with using all the things in the other answers (and from other sources/documentation). What did help was to set the Navigation Bar Style to "Black" in the XIB. This changed the text to white without any code at all.
None of that worked for me, so here is a working solution...
In Info.plist, add a row:
UIViewControllerBasedStatusBarAppearance, and set the value NO.
Then in AppDelegate in didFinishLaunchingWithOptions, add these rows:
[application setStatusBarHidden:NO];
[application setStatusBarStyle:UIStatusBarStyleLightContent];
You dont need to do any code for this
You need to add "View controller-based status bar appearance" key in info.plist as follows:
& set its value type to Boolean & value to NO.
Then click on project settings,then click on General Tab & under Deployment Info set the preferred status bar style to .Light as follows:
Thats it.
Just two steps as following:
Step 1:
Under the Info tab of the project target, Add Row:
UIViewControllerBasedStatusBarAppearance, set value NO.
Step 2:
In the project AppDelegate.m:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
…
[application setStatusBarStyle:UIStatusBarStyleLightContent];
…
}
This works in Golden Master iOS 7 and Xcode 5 GM seed and iOS7 SDK released on September 18th, 2013 (at least with navigation controller hidden):
Set the UIViewControllerBasedStatusBarAppearance to NO in the
Info.plist.
In ViewDidLoad method or anywhere, where do you want to change
status bar style:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
In case your UIViewController is inside a UINavigationController you will have to set the BarStyle:
-[UINavigationBar setBarStyle:UIBarStyleBlack]
Original Answer is here
https://devforums.apple.com/message/844264#844264
If you have an embedded navigation controller created via Interface Builder, be sure to set the following in a class that manages your navigation controller:
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
That should be all you need.
I'm using Xcode 6 beta 5 on a Swift project, for an iOS 7 app.
Here is what I did, and it works:
info.plist:
Go to Project -> Target,
Then set Status Bar Style to Light. It makes status-bar white from the launch screen.
Then set View controller-based status bar appearance equal to NO in Info.plist.
In Swift 3 is very easy just with 2 steps.
Go to your info.plist and change the key View controller-based status bar appearance to "NO".
Then in the Appdelegate just add this line in didfinishlaunchingwithoptions method
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
UIApplication.shared.statusBarStyle = .lightContent
return true
}
this has been deprecated in iOS9 now you should do override this property in the rootviewcontroller
doing this has been deprecated in iOS 9 should do this on the rootviewcontroller
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
In AppDelegate.m, add the following.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
And in the Plist file, set 'View controller-based status bar appearance' to NO.
Simply In App Delegate:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
In Swift 5, Follow the below steps:
Add key UIViewControllerBasedStatusBarAppearance and set value to false in Info.plist
Add key UIStatusBarStyle and set value to UIStatusBarStyleLightContent
Well, this is really working like a piece of cake for me.
Go to your app's info.plist.
Set View controller-based status bar appearance to NO
Set Status bar style to UIStatusBarStyleLightContent
Then go to your app's delegate and paste in the following code where you set your windows's RootViewController.
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
{
UIView *view=[[UIView alloc] initWithFrame:CGRectMake(0, 0,320, 20)];
view.backgroundColor=[UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0];
[self.window.rootViewController.view addSubview:view];
}
Bingo. It's working for me.
iOS 7 allows individual view controllers to determine the appearance of the status bar, as described by the Apple developer documentation:
iOS 7 gives view controllers the ability to adjust the style of the status bar while the app is running. A good way to change the status bar style dynamically is to implement preferredStatusBarStyle and—within an animation block—update the status bar appearance and call setNeedsStatusBarAppearanceUpdate.
Setting the status bar appearance globally is a two-step process.
First, you need to tell iOS that you don't want to set the status bar appearance on a view-by-view basis.
Then you need to take charge and actually set the new global status bar style.
To disable view-by-view status bar control, you'll need to set the View controller-based status bar appearance property in Info.plist.
Open the Project Navigator and select the project for your iOS app, then select the Info tab.
Hover over a row, then click the plus sign that appears to add a new property to your .plist.
Enter View controller-based status bar appearance in the Key field, then make sure the Type field is set to Boolean. Finally, enter NO in the Value field.
To set a global style for the status bar, add another property under the Info tab with a key of Status bar style, a Type of String and a Value of Opaque black style.
Here's a blog post with a little more detail and some sample code:
http://codebleep.com/setting-the-status-bar-text-color-in-ios-7/
Xcode constantly seems to change this, so this is the latest.
As of 2021 - Swift 5, Xcode 12
To change the status bar to white:
Open your Info.plist.
Add key UIViewControllerBasedStatusBarAppearance and set value to No (false). The human readable version of this is "View controller-based status bar appearance".
Add key UIStatusBarStyle and set value to UIStatusBarStyleLightContent (i.e., "Light Content").
Answer updated for for Xcode GM Seed:
In Info.plist put View controller-based status bar appearance as NO
In the project, set:
In ViewDidLoad:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
No need do some extra , just write this code in your viewController and get status bar color white
- (UIStatusBarStyle)preferredStatusBarStyle{return UIStatusBarStyleLightContent;}
I think all the answers do not really point the problem because all of them work in specific scenarios. But if you need to cover all the cases follow the points bellow:
Depending on where you need the status bar light style you should always have in mind these 3 points:
1)If you need the status bar at the launch screen or in other places, where you can't control it (not in view controllers, but rather some system controlled elements/moments like Launch Screen)
You go to your project settings
2) if you have a controller inside a navigation controller
You can change it in the interface builder as follows:
a) Select the navigation bar of your navigation controller
b) Then set the style of the navigation bar to "Black", because this means you'll have a "black" -> dark background under your status bar, so it will set the status bar to white
Or do it in code as follows
navigationController?.navigationBar.barStyle = UIBarStyle.Black
3) If you have the controller alone that needs to have it's own status bar style and it's not embedded in some container structure as a UINavigationController
Set the status bar style in code for the controller:
Here is Apple Guidelines/Instruction about status bar change. Only Dark & light (while & black) are allowed in status bar.
Here is - How to change status bar style:
If you want to set status bar style, application level then set UIViewControllerBasedStatusBarAppearance to NO in your `.plist' file.
if you wan to set status bar style, at view controller level then follow these steps:
Set the UIViewControllerBasedStatusBarAppearance to YES in the .plist file, if you need to set status bar style at UIViewController level only.
In the viewDidLoad add function - setNeedsStatusBarAppearanceUpdate
override preferredStatusBarStyle in your view controller.
-
override func viewDidLoad() {
super.viewDidLoad()
self.setNeedsStatusBarAppearanceUpdate()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
Set value of .plist according to status bar style setup level.
Here is some hacky trick to change/set background color for status bar during application launch or during viewDidLoad of your view controller.
extension UIApplication {
var statusBarView: UIView? {
return value(forKey: "statusBar") as? UIView
}
}
// Set upon application launch, if you've application based status bar
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.statusBarView?.backgroundColor = UIColor.red
return true
}
}
or
// Set it from your view controller if you've view controller based statusbar
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
UIApplication.shared.statusBarView?.backgroundColor = UIColor.red
}
}
Here is result:
This is documented in the iOS 7 UI Transition Guide, which you need an Apple developer ID to access directly. The relevant excerpt:
Because the status bar is transparent, the view behind it shows through. [...] Use a UIStatusBarStyle constant to specify whether the statusbar content should be dark or light:
UIStatusBarStyleDefault displays dark content. [...]
UIStatusBarStyleLightContent displays light content. Use when dark content is behind the status bar.
Also possibly of interest:
In iOS 7, you can control the style of the status bar from an individual vew controller and change it while the app runs. To opt in to this behavior, add the UIViewControllerBasedStatusBarAppearance key to an app's Info.plist file and give it the value YES.
I'd definitely recommend having a look through the document, which, again, you can access with your Apple developer ID.
Simply calling
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
in the
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
}
method of my AppDelegate works great for me in iOS7.
In my case for Swift 5, I added these lines:
override func viewDidAppear(_ animated: Bool) {
navigationController?.navigationBar.barStyle = .black
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
I did some things different and it works for me.
With no changes in code, I did config my .plist file like this:
View controller-based status bar appearance > NO
Status bar style > UIStatusBarStyleLightContent (simple string)
I hope it helps.
edit
For each view controller I change the "status bar"'s Simulated Metrics property, in storyboard, from "inferred" to "Light Content"
in info.plist set the field value NO View controller-based status bar appearance and set statusbar style light in target > general setting.
Just to summarize, edit your project Info.plist and add:
View controller-based status bar appearance : NO
Status bar style : Opaque black style
or if you have raw key/value plist
UIViewControllerBasedStatusBarAppearance : NO
UIStatusBarStyle : Opaque black style
If you want the same result with Swift, you can use this code in your AppDelegate.swift file :
UINavigationBar.appearance().barStyle = .BlackTranslucent
And the text of your status bar will be white :-) !