Change appearance of UINavigationBar from solid to transparent - objective-c

I want to achieve the exact same effect as the Photos app on the iPad: solid black navigation bar during the gallery controller, then transparent when viewing a photo.
After I initialize my navigation controller in the AppDelegate I can change the style using the below code, but not outside the AppDelegate. However once the navigation controller is on screen and set once, navigationBar becomes a read-only property.
I would greatly appreciate if someone can share how this is done. Thanks.
self.navigationController.navigationBar.tintColor = [UIColor clearColor];
self.navigationController.navigationBar.translucent = YES;
self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;

UINavigationBar in UIBarStyleBlackTranslucent barStyle doesn't fix it's place as it normally does in other styles. In UIBarStyleBlackTranslucent style it just overlaps on your view and contents of views are translated up and view height is also increased.
if you're showing photos then first hide your navigationBar :
[[self navigationController] setNavigationBarHidden:YES animated:NO];
Now set your navBar's style to UIBarStyleBlackTranslucent
[self.navigationController.navigationBar setBarStyle:UIBarStyleBlackTranslucent];
Then show your imageview (or scrollview with picture- depends on your logic). Then on tapping on your imageview you can show and hide bar)
// Show/Hide bar
// Let say you've a bool 'shown' for current status of navbar's visibility.
if (!shown) {
[[self navigationController] setNavigationBarHidden:YES animated:YES];
}else{
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}
shown = !shown;
Hope this'll do it. ANd never forget to rechnage barStyle to UIBarStyleBlackOpaque once you exit gallery.

Seems like you want to display navigationBar at the Gallery so there no need to change anything but after selecting a photo, keep the NavigationBar hidden in the PhotoViewController.
-(void) viewDidLoad
{
self.navigationController.navigationBar.barStyle=UIBarStyleBlackTranslucent;
self.navigationController.navigationBar.hidden = NO;
}
and in ViewWillAppear
-(void) viewWillAppear
{
self.navigationController.navigationBar.hidden = YES;
}
And then create a custom method implementing UITapGestureRecognizer where on a single tap display the navigationBar by setting hidden property to YES.

Related

Hide status bar in iOS7

I need to hide the status-bar on iOS7. I already tried to set:
Status bar is initially hidden
and
View controller-based status bar appearance
into the plist file. Status-bar doesn't appears when app in launched, but when I change view-controller (is a tabbed app) status-bar appears!
I already tried to set
- (BOOL)prefersStatusBarHidden
{
return YES;
}
and
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
in a view-controller, but doesn't works. Any ideas?
Thank you in advance :)
UPDATE
I partially resolve the issue by setting "View controller-based status bar appearance" to "YES" into info.plist and calling the method
- (BOOL)prefersStatusBarHidden
{
return YES;
}
into the view-controller. But now I got another problem: status-bar appears when I launch another controller (UIImagePickerController). I tried to set [myPicker prefersStatusBarHidden]; but it seems to be read-only. Anyone know the solution?
P.S.: UIViewControllerBasedStatusBarAppearance = NO and UIViewControllerBasedStatusBarAppearance = NO are the same thing..
add this key to your info.plist
UIViewControllerBasedStatusBarAppearance = NO
Set
UIViewControllerBasedStatusBarAppearance = YES
in the info.plist and in each controller implement
- (BOOL)prefersStatusBarHidden {
return YES; // or NO
}
Then whenever you need a status bar appearance update (e.g. in the viewDidLoad of a controller) call setNeedsStatusBarAppearanceUpdate.
As per the documentation of setNeedsStatusBarAppearanceUpdate:
Call this method if the view controller's status bar attributes, such as hidden/unhidden status or style, change. If you call this method within an animation block, the changes are animated along with the rest of the animation block.
So for instance
- (void)viewDidLoad {
[super viewDidLoad];
[self setNeedsStatusBarAppearanceUpdate];
...
}
will hide/unhide the status bar (aside from other potential style changes) whenever the view controller's view loads.
Optionally you can also animate the transition wrapping the call in an animation block
- (void)viewDidLoad {
[super viewDidLoad];
[UIView animateWithDuration:0.5 animations:^{
[self setNeedsStatusBarAppearanceUpdate];
}];
...
}

Why does my Navigation Bar temporarily disappear when I dismiss a modal view in iOS 7?

When I'm going back from my Modal View Controller to my Main View Controller (I have a horizontal animation) my Main Controllers navbar places itself a bit too high for a quick second and then jumps back to its right position. Does somebody know why? Ive been googling it but with no success.
App Delegate:
[navigationController.navigationBar setBarTintColor: [UIColor whiteColor]];
[navigationController.navigationBar setTranslucent: NO];
When i push button to open my Info View:
UIViewController *infoViewController;
infoViewController = [[InfoViewController alloc] initWithNibName:#"InfoViewController" bundle: nil];
infoViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController: infoViewController animated: YES completion:nil];
I'm not using Auto Layout on any xib-files. My Main View Controller xib-file is empty with Status Bar: Default. My Info View Controller xib-file has some stuff in it.
Code for closing my Modal View Controller:
-(IBAction)onBackBtnClick:(id)sender
{
[self dismissModalViewControllerAnimated: YES];
}
All what you have to do is to add the following code in the ViewWillAppear of the "InfoViewController" viewController class
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.navigationController.navigationBar setTranslucent:NO];
[self.navigationController.navigationBar.layer removeAllAnimations];
}
Hope it worked with you :)
The problem seems to be
infoViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
If you change this to
infoViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
then it will no longer jump. This worked for me. Good luck!

Recipients field of MFMessageComposeViewController doesn't show in iOS 7

The code below works fine in iOS 5/6. In iOS 7, it looks like this (red oval for emphasis).
Code:
if ([MFMessageComposeViewController canSendText]) {
self.messageComposer = [MFMessageComposeViewController new];
self.messageComposer.recipients = #[number];
self.messageComposer.messageComposeDelegate = self;
[self presentViewController:self.messageComposer
animated:YES
completion:nil];
}
Question: This is simple code. Is there some other external property, perhaps of the presenting view controller, that is affecting this? Anyone have a fix or workaround?
thanks.
I've found that the MFMessageComposeViewController's recipient field seems to take some of it's appearance from the UINavigationBar appearance proxy in iOS7. To work around this, I've done the following in my apps:
Create an empty custom UINavigationController subclass, which doesn't override any of UINavigationController's methods.
Use this custom UINavigationController subclass as a marker for any navigation controllers that I want to have custom appearance, by setting the custom class on the identity inspector in IB:
In my app delegate, set up the appearance of navigation bars like this:
[[UINavigationBar appearanceWhenContainedIn:[MyCustomNavigationController class], nil] ...];
This ensures that I get the navigation bar appearance I want in the controllers I want to customize, but preserves the standard navigation bar (and related) appearance in other controllers (like MFMessageComposeViewController). Here's a screenshot; note the standard appearance of MFMessageComposeViewController, with the custom navigation bar appearance on the popover in the background:
I faced same problem and here is my solution-
Before presenting your message composer( [self presentViewController:messageComposer animated:YES completion:nil]; )
set
[[UINavigationBar appearance] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
and in delegate method
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result {
UIImage *backgroundImage = [UIImage imageNamed:#"Navigation Bar"];
[[UINavigationBar appearance] setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
[self dismissViewControllerAnimated:YES completion:nil];
}
Thats all!!

Presenting a modal view controller with cross-disolve isn't showing views added in code

When I present a modal view controller over my view storyboard originated root view controller it flashes the story board view, even if it has been altered. My root view controller has a bright green back ground with large white subview across the top that contains a label bound to an IBOutlet. In UIViewController viewDidLoad I am adding a light gray, slightly transparent UIView that covers the entire view as a subview of the viewcontroller's view. I am also setting the label text to be different than that of the Storyboard layout.
When I trigger the modal, either via segue or via presentViewController:completion: what I see is the light gray view over my label then the view added in code seems to become transparent and animate away and the bright green of the storyboard layout shows up and then the modal view cross-dissolves in. When I dismiss the first and present the second in the completion block i see a cross-dissolve to bright green, pop of light as the added view becomes visible again, pop to bright green and the cross-dissolve in of the second view controller's view.
When I dismiss the second view controller then I see cross-dissolve out to the bright green and then the added light gray, semi-transparent view pops back to being visible.
Anyone have any idea how to stop the cross-dissolve from showing the views underneath the view added in code?
This example is made more jarring if you remove the opacity from the overlay view added in viewDidLoad.
https://github.com/jonnolen/ios-cross-disolve-problem
Code snippet and story board layout:
#interface DTViewController (){
BOOL hasShownSegue;
}
#end
#implementation DTViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UIView * view = [UIView new];
view.frame = self.view.bounds;
view.backgroundColor = [UIColor colorWithWhite:.95 alpha:.7];
NSLog(#"View Bounds: %#", NSStringFromCGRect(self.view.bounds));
[self.view addSubview:view];
self.label.text = #"Hello!";
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
if (!hasShownSegue){
[self performSegueWithIdentifier:#"modal.1.segue" sender:self];
hasShownSegue = YES;
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
DTCallbackViewController *vc = segue.destinationViewController;
vc.completionCallback = ^{
[self dismissViewControllerAnimated:YES completion:^{
DTCallbackViewController * vc = [self.storyboard instantiateViewControllerWithIdentifier:#"vc.2"];
vc.completionCallback = ^{
[self dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:vc animated:YES completion:nil];
}];
};
}
Figured it out, I don't really like it but it works:
I put all of the maskable content into a separate view:
And then hide that view when I need it to be "masked".
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"View Bounds: %#", NSStringFromCGRect(self.view.bounds));
self.label.text = #"Hello!";
self.content.hidden = YES;
}
Then animations behave as expected. However, this only works with an opaque mask (which is what I needed).

UIScrollView shifts below navigation and status bar

I have view which contains a scrollView. When the view shows up the image appears in full screen (320x480) hiding the status and navigation bar. When I tap the screens - status and navigation bar appears on the screen. But this thing shifts the UIScrollView below the the navigation bar. I want the status and nav bar to show over my scroll view.
Like it happens in the photos app. On tapping the image the status and nav bar shows over the scrollView.
Below is how I am positioning the view
//What I have done in viewDidLoad
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
self.wantsFullScreenLayout = YES;
scrollView = [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view = scrollView;
Below is what I am doing on detecting a single tap
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotSingleTapAtPoint:(CGPoint)tapPoint {
// single tap hide/unhide the status and nav bar
NSLog(#"got a single tap");
if (self.navigationController.navigationBarHidden == NO)
{
[self.navigationController setNavigationBarHidden:YES animated:NO];
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
}
else
{
[[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES];
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
}
Just a pointer for you guys -
If I use [self.view addSubview:scrollView]; I dont see this issue. But this mess up my landscape orientation code.
Anyone who can shed some light what I might be doing wrong - would be great help!
There appears to be some special handling inside UIScrollView when the navigation toolbars are toggled. As you pointed out at the end of your question, if you put the scroll view inside a containing UIView, this repositioning problem does not occur.
To fix the landscape issues, make sure you're setting the autoresizingMask on both the container view and the scroll view. I did not have to add any additional handling for landscape mode in my project.
I found the solution myself.
In my tap detecting code's else fn I add the below line in the last.
scrollView.contentOffset = CGPointMake(parentScrollView.contentOffset.x,0);
Not sure if this is the right approach. But if anyone can suggest a better approach - more than welcome!