Change color of UIDocumentInteractionController nav bar - objective-c

Is there a way to change the tint/background color of UIDocumentInteractionController navigationbar?

A cleaner version of #DOOManics implementation:
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
return [self navigationController];
}

If you put the UIDocumentInteractionController onto a UINavigationController it will automatically take the color its navbar. This is probably your root view navcontroller.
You do this with the documentInteractionControllerViewControllerForPreview method:
- (UIViewController *) documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller
{
// Use the rootViewController here so that the preview is pushed onto the navbar stack
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
return appDelegate.window.rootViewController;
}

[[UINavigationBar appearance] setTintColor:[UIColor colorWithRed:107.0/256.0 green:145.0/256.0 blue:35.0/256.0 alpha:1.0]];
Place this code in Appdelegate's didFinisLaunching method. It will change the color of the navigation bar for the whole app.

Try this code:
- (void)openEC:(NSURL*)url {
[UINavigationBar appearance].tintColor = [UIColor blueColor];
docController = [UIDocumentInteractionController interactionControllerWithURL:url];
[docController setDelegate:self];
[docController presentOptionsMenuFromRect:self.view.bounds inView:self.view animated:YES];
}
- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller {
[UINavigationBar appearance].tintColor = [UIColor whiteColor];
}

Swift version to #dvdfrddsgn implementation
Try this : (You need to implement UIDocumentInteractionControllerDelegate)
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self.navigationController ?? self
}

If you're not using a navigationController, you can set the navigation bar color in the UIDocumentInteractionController by setting the correct settings on the View of the UIViewController where you launch the UIDocumentInteractionController from.
Let's say you have UIViewController viewController1 (from somewhere here you launch the UIDocumentInteractionController), with a View1 in the storyboard.
With the Storyboard open, click on the View1 from the list of elements on the viewController1 and go to "Attributes inspectors" on the right side. The Background and the Tint set there will be used in your UIDocumentInteractionController as well afterwards.
Then you can just use:
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
return self;
}
Note that inside the viewController1, you might have a Navigation Bar with different properties, and these will not be used in the UIDocumentInteractionController.

Related

UIImagePickerController breaks status bar appearance

In my .plist file, I have "View controller-based status bar appearance" set to NO. But after UIImagePickerController, my app behaves as if the option is set to YES.
In my app, I present a VC that presents a UIImagePickerController.
The problem happens like this:
After photo picker is presented, when a photo library is picked, the color of the status bar text changes.
Then once, UIImagePickerController is dismissed, status bar spacing
changes for the rest of my app and all the navigation bar for other controllers displays under the status bar.
Is there a way to solve this without managing status bar in my view controllers?
None of the solutions above worked for me, but by combining Rich86man's and iOS_DEV_09's answers I've got a consistently working solution:
UIImagePickerController* imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
and
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
Regarding this awesome solution. For 2014 / iOS8 I found in some cases you need to ALSO include prefersStatusBarHidden and, possibly, childViewControllerForStatusBarHidden So...
-(void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
-(BOOL)prefersStatusBarHidden // iOS8 definitely needs this one. checked.
{
return YES;
}
-(UIViewController *)childViewControllerForStatusBarHidden
{
return nil;
}
-(void)showCamera
{
self.cameraController = [[UIImagePickerController alloc] init];
self.cameraController.delegate = (id)self; // dpjanes solution!
etc...
I faced this same issue today. Here is my solution.
In the view controller who calls the image picker, set yourself as the delegate of the image Picker. (You're probably already doing this)
UIImagePickerController* imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
Since UIImagePickerController is a type of Navigation controller, you're also setting yourself as the UINavigationController delegate. Then :
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
Replace UIStatusBarStyleLightContent with whatever style you are looking for.
The accepted answer will work if you have the 'View controller-based status bar appearance' set to NO in your .plist file. If indeed you need to control the status bar in some other view controllers and have this option set to YES, the other way to make UIImagePickerController to behave correctly is by subclassing it
// .h
#interface MYImagePickerController : UIImagePickerController
#end
// .m
#implementation MYImagePickerController
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent; // change this to match your style
}
#end
i faced the same problem.
here is my solution.
put this in the viewWillAppear of the view controller from which you are opening the image pickerview
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
Can you try this. I think needsStatusBarApperanceUpdate will work.
1 -Set UIViewControllerBasedStatusBarAppearance to NO.
2- Call [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
3- [self setNeedsStatusBarAppearanceUpdate];
I found this to offer proper handling, there's two parts.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
...
the UIImagePickerController itself presents view controllers, so this delegate works for all presenters on the stack.
the viewWillAppear ensures this view controller itself is always reset whenever a presenting view controller dismisses above it.
I had the same problem.
Add in info plist: "View controller-based status bar appearance" with value "NO"
Example here https://stackoverflow.com/a/19211669
This solution works for me.
This is probably a bug. I solved the problem by setting "View controller-based status bar appearance" set to YES and in every view controller pasting in the following code:
- (BOOL)prefersStatusBarHidden
{
return YES;
}
Then my app behaves as expected.
For hiding the status bar in UIImagePicker :
-
(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
and when UIImagePicker is dismissed to hide the status bar in View controller use the following code :
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
try this ....
this will work in both cases i.e whether you use presentModalViewController and pushViewController
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
delegate methods
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[picker dismissViewControllerAnimated:YES completion:^{}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[picker dismissViewControllerAnimated:YES completion:nil];
}
All the above didn't work for me. I solved the issue by changing the presentation style to:
imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
None of the above solutions worked for me.
I present UIImagePickerController as modal view controller. After dismissing UIImagePickerController the status bar state was:
[UIApplication sharedApplication].statusBarOrientation = 0 (UIDeviceOrientationUnknown)
[UIApplication sharedApplication].statusBarFrame = { 0, 0, 0, 0}
The solution that fixed the problem for me was restoring statusBarOrientation after dismissing UIImagePickerController:
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
[self.viewController presentViewController:cameraUI animated:true completion:^(void){ }];
...
[self.viewController dismissViewControllerAnimated:animated completion:^(void){
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
}];
This code helped me to customize status bar style.
EDIT: this solution works if "View controller-based status bar appearance" == YES
#implementation UIImagePickerController (IOS7_StatusBarStyle)
-(UIViewController*)childViewControllerForStatusBarStyle
{
return nil;
}
-(UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
#end
All the answers above is ok and can help.
I had the same problem having to manage the application runned under different iOS versions.
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
if(IS_IOS8_AND_UP) {
imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
} else {
imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
}
imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:YES completion:nil];
Then, in delegate:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
/* Cancel button color */
_imagePicker.navigationBar.tintColor = <custom_color>
/* Status bar color */
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
}
Yet another solution which may work in some of the situations.
let imagePicker = UIImagePickerController()
imagePicker.sourceType = .PhotoLibrary
imagePicker.navigationBar.barStyle = .Black
Have you tried calling [self setNeedsStatusBarAppearanceUpdate] when your presenting view controller reappears?
I try to hide the status bar in UIImagePickerController in iOS7, but I still don't know how to do this. I use
- (void)viewWillAppear:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:YES
withAnimation:UIStatusBarAnimationNone];
}
in the ViewController that call the UIImagePickerController, and set "View controller-based status bar appearance = NO" in the plist file. Hope this can help.
try this :
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
and in the protocol implement, use this:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
This solved it for me...:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[picker dismissViewControllerAnimated:YES completion:nil];
}
Nothing here specifically fixed the problem in that I was having (and perhaps that the OP was having too), so I thought I would share my answer. Instead of hiding the status bar which I think is a buggy solution (I noticed that it would sometimes leave my app in a state where the status bar was hidden when it shouldn't be). I instead opted to try and play nice with the UIStatusBarStyles.
When the UIImagePickerController has its view presented I set the status bar style to default since the default background color is a light grey.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];
}
Then, when the image picker is dismissed, I set it back to the UIStatusBarStyleLightContent.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//work
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
//work
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
[self dismissViewControllerAnimated:YES completion:NULL];
}
In this case,We are using 2 steps
In first step:
Add in info.plist: "View controller-based status bar appearance" with value "NO"
In Second step: Use/call this code with delegate of UIImagePickerController
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if([navigationController isKindOfClass:[UIImagePickerController class]])
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
In case of IOS-7 add One more Function
- (BOOL)prefersStatusBarHidden
{
return YES;
}
As of iOS 8.1, it seems like they've finally fixed this bug! I was able to remove all of the workarounds I employed from my code.
Using the default iOS 8 behaviour I was having problems with the status bar appearing when I wanted it hidden.
The solution I found was that, directly after calling presentPopover from my view controller I did:
[self performSelector:#selector(setNeedsStatusBarAppearanceUpdate) withObject:nil afterDelay:0.01];
I also had to add this to my main view controller:
- (UIViewController *)childViewControllerForStatusBarHidden
{
return nil;
}
So I had this problem and I was able to solve it by simply implementing a single delegate function. The background of my status bar is black, and so UIStatusBarStyle for my application is .LightContent. When I presented the UIImagePickerController to select a photo from the device storage, the status bar was fine. However, upon clicking into a directory such as "Camera Roll" or "Favorites," effectively pushing onto the navigation stack, the status bar disappeared. Upon selecting a photo, there was no status bar at all; upon dismissing another modal view controller, only the battery was present, indicating the rest of the status bar may be black as well.
I tried some of the other solutions such as extending UIImagePickerController, but in Swift, you cannot override using extensions. I then tried to subclass UIImagePickerController and tried to hide its status bar on viewWillAppear() and unhiding the status bar on viewWillDisappear. I was able to see the status bar hide with a .Slide animation, but since the status bar was invisible upon selecting a directory, I was not able to see the status bar unhide. Again, the green battery came back with the rest of the status bar invisible upon dismissing a modal view controller. I also tried overriding prefersStatusBarHidden(), but that function was never called, so I tried calling setNeedsStatusBarAppearanceUpdate() to ensure that prefersStatusBarHidden() is called by the system, but it still is not called. Also, there is the suggestion to set the status bar to be hidden on the delegate method navigationController willShowViewController. Once again, all this does is hide the status bar, which does not solve the problem. As it turns out, it seems that the status bar style is changed upon pushing onto the navigation stack of the UIImagePickerController. To solve the problem entirely, I did not have to write extensions or subclass UIImagePickerController. All you need to do is set the delegate and set the status bar style to remain the same. This addition made it as if the problem never existed.
let pickerController = UIImagePickerController()
pickerController.delegate = self
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
UIApplication.sharedApplication().setStatusBarStyle(.LightContent, animated: false)
}
I actually found a better way to set the status bar background color in Image Picker. Basically you need to set the backgroundImage from the navigationBar to nil, because is default in Image Picker has a backgroundImage as a white Image.

UINavigationController TitleView - Need clarification

Okay, there's one thing I really don't understand.
I have a navigation controller (created in AppDelegate.m) as the first item in a tab bar controller (created in AppDelegate.h):
self.tabBarController.viewControllers = #[tabOneNavigationController, viewController2, viewController3, viewController4, viewController5];
In another class, I access this tabOneNavigationController by:
AppDelegate *apd = (AppDelegate *) [[UIApplication sharedApplication] delegate];
UINavigationController *navtab1 = [apd.tabBarController.viewControllers objectAtIndex:0];
And if I want to change the background of navtab1's navigation bar, I write:
[navtab1.navigationBar setBackgroundImage:navigationBackgroundImage forBarMetrics:UIBarMetricsDefault];
But for changing titleView, I've only seen examples using:
self.navigationItem.titleView = ...
but how do I do change navtab1's titleView?
Example: I have a custom TableViewCell, which contains a button, and when that button's clicked, it should change the titeView of navtab1 (in this case, self obviously doesn't have navigationItem property.
Here is use delegate methode of UINavigationController, This code might be helpful in your case:
#pragma mark -
#pragma mark - UINavigationController Delegate Methods
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
UINavigationBar *morenavbar = navigationController.navigationBar;
UINavigationItem *morenavitem = morenavbar.topItem;
morenavitem.titleView = myCustomeView; // Add Here your custom UIView.
morenavitem.rightBarButtonItem.tintColor = [UIColor blackColor];
}
In above Method you also put image/color of NavigationBar.

switch for a TabBarView without StoryBoard

I have a ConnectionViewController and when i click on the Test button, i would like to switch for a tabViewController.
In my ConnectionViewController :
- (IBAction)testButton:(id)sender {
TabBarViewController *tabBarViewController = [[TabBarViewController alloc] init];
[self presentViewController:tabBarViewController animated:YES completion:nil];
}
but when i click on my test button, the TabBarView is black, without anything.
What could i do to fix that ? I would like a modal segue, not a push.
Thx a lot
[EDIT] : The solution is to create a custom segue with a class like CustomSegue.m with this method :
-(void) perform {
ConnectionViewController *src = (ConnectionViewController*) self.sourceViewController;
TabBarViewController *dest = (TabBarViewController*) self.destinationViewController;
[UIView transitionWithView:src.navigationController.view duration:0.2 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
[src presentViewController:dest animated:YES completion:NULL];
}
completion:NULL];
}
The reason why the tab bar controller is black is that it does not have any viewControllers to present. You need to set tabBarController.viewControllers property before you present it. Lets say you want to present a tabBarViewController with viewController1 on the first tab and viewController2 on the second tab.
tabBarViewController.viewControllers = #[viewController1, viewController2];

Back button not appearing on UINavigationController

I have a UINavigationController setup in my AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add the navigation controller's view to the window and display.
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
In my RootViewController I am pushing another view onto the stack:
//Show the deals
DealViewController *dvc = [[DealViewController alloc] initWithNibName:#"DealViewController" bundle:nil];
[self.navigationController.navigationBar setHidden:NO];
[self.navigationController pushViewController:dvc animated:YES];
The view shows up, but there is no back button that is added to my navigation bar. Why is this and how can I resolve it?
Are you setting self.title in RootViewController? Perhaps the UINavigationController doesn't have any text to put on the back button, so it omits it...?
Are you setting hidesBackButton = YES or backBarButtonItem = nil in DealViewController, or does it have a different leftBarButtonItem defined?
Try this:
DetailViewController *detailViewController = [[DetailViewController alloc] init];
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithTitle : #"Back"
style : UIBarButtonItemStyleDone
target : nil
action : nil];
self.navigationItem.backBarButtonItem = back;
[self.navigationController pushViewController : detailViewController animated : YES];
[detailViewController release];
You must think of the navigation controller as a stack of navigation controllers each controlling one screen full of information.
You instantiate the navigation controller with the
-(id)initWithRootViewController:(UIViewController *)rootViewController
method. You specify the root view controller in this call. Then you add the navigation controller's view as a subview to the window, like you did before.
If you want to show your second screen you push another view controller on the stack by using
-(void)pushViewController:detailViewController animated:YES
method.
Using presentModalViewController to show the naviagtionController. Set the navagitionController bar button like so:
[navigationController.navigationBar.topItem setLeftBarButtonItem:
[[[UIBarButtonItem alloc] initWithTitle: #"Back"
style: UIBarButtonItemStylePlain
target: self
action: #selector(dismisstheModal:)] autorelease]];
This happened to me because in my navigation controller's content controller I had set up some navigation controller behavior in viewDidLoad and in another class that inherits from my content controller, and the one that was being presented, i implemented a viewDidLoad as well, and forgot to call [super viewDidLoad] which thereby caused me to override the base class's viewDidLoad where I was setting up my navigation controller buttons. Oooops.

Can't show a nagivationbar after hiding it

I have the following in the mainwindow.xib
Navigation Controller
List item
Tab bar controller
tabbar
firstViewController
SecondViewController
The entrypoint
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
navController.viewControllers = [NSArray arrayWithObject:tabBarController];
[window addSubview:navController.view];
[window makeKeyAndVisible];
return YES;
}
and now in the first viewcontroller i'm writing
-(void)loadView
{
if(rootAppDelegate==nil)
rootAppDelegate=(tabbarAppDelegate *) [[UIApplication sharedApplication]delegate];
listEmergencyItems= rootAppDelegate.listOfEmergencySectionItems;
self.rootAppDelegate.navController.navigationBarHidden = NO;
[super loadView];
}
and in the second viewcontroller i'm writing
- (void)loadView
{
if(rootAppDelegate==nil){
rootAppDelegate=(tabbarAppDelegate *) [[UIApplication sharedApplication]delegate];
}
listHospitalsItems= self.rootAppDelegate.listOfHospitalsItems;
self.rootAppDelegate.navController.navigationBarHidden = YES;
[super loadView];
}
And on the runtime, when it first loads the first view, i see the navigationbar where i need to navigate into a detail view.
And when i press the second tab bar item, i go to the second view, and the navigation bar gets hidden.
But when i press back on the first tabbar item, i.e. returning to the first viewcontroller. the navigation bar remains hidden.
Any idea?
The navigation bar won't show in the second view because neither view was placed on the navigationcontroller's stack. you want to use something like this in the parent to present a child view instead of overriding loadView
ViewToPresentViewController *myVController = [[ViewToPresentViewController alloc] initWithNibName:#"ViewToPresentViewController"
bundle:nil];
myVController.property = someValue;
[self.navigationController pushViewController:myVController
animated:YES];
[myVController release];
then, as i said previously, you can just use [self.navigationController setNavigationBarHidden:animated:]