Using Autolayout, unable to move the navigation bar down 20px - ios

I have a UITabBarController which has four tabs. One of those tabs opens a my results screen (a UITableViewController).
On showing this screen, I want to move the UINavigationBar down 20px (to make room for a custom UIStatusBar which I show on all screens).
On all my other screens, I add some code to the viewWillAppear method to change the self.navigationController.navigationBar.frame.origin.y to 20.
but these are all "non-root" screens (i.e. a pushed view with a back button).
However on THIS screen the UINavigationBar must be initially visible, even though it is the root view. I use the same code, but it doesn't move the view down.
I'm assuming autolayout is moving it back into position, so I tried adding this code into viewWillLayoutSubviews and viewDidLayoutSubviews. But when I do this the navigationbar doesn't move down until the first time the tableview is scrolled.
What do I need to do to force the navigationBar to move down (and stay down) before the screen appears?

Are you using storyboards? Set the Y in storyboards to 20, Make your viewcontroller implement UINavigation bar, then add this code:
-(UIBarPosition)positionForBar:(id<UIBarPositioning>)bar{
return UIBarPositionTopAttached;
}
This will tell the app that the navigation bar is to be attached, it will remain at 20px but extend the background all the way up.. So essentially it'll look like it's at y = 20.

Related

Keyboard flashes from opaque to transparent upon push

I have a view embedded in a navigation and tab bar controller. When a button is pressed, it pushes to (shows) the next view and I programmed the keyboard to immediately show for the first text field [textField becomeFirstResponder].
However, the keyboard will be opaque instantly then turn transparent in a little less than half a second. This happens no matter the keyboard type or keyboard look. I have no idea what is causing this, and I cannot find any answers anywhere else.
Other details: the navigation bar is translucent, and the bottom bar is hidden on the view we push to. The background is an image. This problem does not occur if I remove [textField becomeFirstResponder] and have the user just select the text field, but that is not what I am trying to do.
I have a similar scenario and also ran into this issue.
I am push-segueing between view controllers, and the keyboard has to stay up during the segue (textField.becomeFirstResponder() is called in viewWillAppear(_:)). The view controllers' background is white, but the keyboard look is Dark. During the segue, the keyboard is black, and then turns gray as soon as the segue finishes.
I came up with a workaround for that - it works if you want to have the keyboard opaque-ish at all times.
Add an empty UIView to the view controllers where you want to show the keyboard instantly, and set the backgroundColor of the view to match your keyboard's look (black for Dark, white for Light). Pin that view to left, right and bottom edges of the view controller's safe area superview. Add a height constraint to it equal to 0 and make an IBOutlet for it.
In your view controller, subscribe to KeyboardWillShow and KeyboardWillHide notifications and control the height constraint of the view you created - make it match the keyboard's frame height (the keyboard's frame end).
You will still see that during the segue, the keyboard stays opaque, but when the segue finishes and keyboard transparency kicks in, the effect is much less visible.
Ideal scenario for me would be to be able to turn off the transparency of the keyboard completely, but I don't think it's possible. I also think there is no way to make the keyboard non-opaque during the segue, so the only option is to make it look opaque at all times.

Navigation bar prompt & height resize animation

Good day!
I have an embedded navigation bar in my app.
mainView is a ViewController with tableView in it.
On first launch there is no prompt text on navigation bar. When you get to options (second view controller) you can set a text to your main views prompt. So after you do so, returning from "Options" to mainView triggers nice and smooth animation on navigation bar increasing its height and prompt text appears.
When i launch the app for the second time, where prompt text is loaded, the text is ok, the size is ok, but the animations of height resize start to get glitchy when switching views, navigation bar height jumps from big to small w/o animation, although text appears to dissolve as usual.
Here is an example of where i switch views in a loaded app:
If i go to options view controller and again set the prompt text -> animation of height increase between views gets fine.
I'm sure i am missing something at launch, something like tableView.reloadData() in viewDidLoad, but for navigation bar.

UIPageController inside UINavigationController is offset from the top?

This a little bit wierd i have made UIPageController that works and everything is fine. But when i put it inside UINavigationController, it offset from the for status bar. Than i swipe up on that screen it positions itself right and everything is ok. I don't really understand what is happening. Here are the images
try setting adjustScrollViewInsets to false on UIPageController.
This is the property that determines whether the system should automatically add inset to a UIScrollView in your view controller's view hierarchy when it is being displayed behind transparent bars (here , the navigation bar). What happened here is that the system assumed the bounds of the page controller overlaps with that of the nav bar and so it adds insets so that the view's contents is fully visible and is not obscured by the nav bar. But in this case it is wrong since it seems your page controller's bounds starts at the bottom edge of the nav bar.
I think you can also set the nav bar as opaque to disable the automatic adding of insets.

Add a UIImageView to the back of NavigationBar (NOT background image)

I am trying to add a UIImageView to the back of a navigation bar.
The reason is because I want to create a UITableView whose navigation bar is actually a picture (with back button on the left) but I want the picture to scroll with the tableview and when the picture is fully scrolled out. The navigation bar is shown as per normal.
My solution to this problem:
Add a UIImageView to the top of the UITableView and make the navigation bar transparent. Set a contentOffset for the UITableView which is a subclass of UIScrollView so that when the view is presented, it looks like the picture is filling the navigation status bar.
Problem:
If I scroll up, instead of bouncing back, the transparent status bar is shown (with a color of the background as it is transparent).
Possible way to solve this new problem:
I was thinking of trying to limit the ScrollView size to get around with problem but failed.
So I feel is it possible to add the UIImageView to the "back" of the navigation bar so that it is there without any offset? Since that way, my life will be much easier.
Any suggestions on solving this or another new approach to get the same UI/effect?
Related question.
I would do this by adding either a table header or cell at the top of the table which contains your image.
Create the table view so that it extends all the way to the top of the screen. Extend Under Top Bars option. I have not done this with a UITableViewController but I have done this with a UITableView embedded inside a UIViewController's view with the top constraint set to 0 for the view rather than the top layout guide.
Now when you run this your table will fill the whole screen and the top header or cell will be at the top showing your picture.
When you scroll you can either use the UIScrollViewDelegate to detect the movement or implement tableView:didEndDisplayingCell:forRowAtIndexPath:
I'm not 100% sure when you want the navigation bar to go non clear. If its when the image goes off screen then didEndDisplayingCell should be good. If its when the cell bottom passed under the bottom of the navigation bar then scroll view might be your only option.
This will also bounce as you expect when you pull down and it should snap back to the top.
Hope this helps.

Animate Controls down with change to UINavigationBar

I have a UINavigationController with standard UINavigationBar. When presenting certain UIViewControllers and orientations, the UINavigationBar may or may not appear and it may or may not have a prompt element. This means that the bar height changes frequently.
I have some subviews below the UINavigationBar set with NSLayoutConstraints to topLayoutGuide. It generally lays out as expected, adjusting vertical position of the subviews appropriately based on the height of the UINavigationBar. What it does not do is move the subviews at times when the UINavigationBar is animated after the view is already displayed.
Specifically, coming from a state with UINavigationBar hidden, transition to a UIViewController which does not hide the navigation bar to one which does. The view displays, then navigation bar animates into place. The subviews do not move down. If I rotate the device, every things lays out appropriately again. Only when animating the navigation bar in and out or to display/hide the prompt I not find a hook to reevaluate the constraints.
I tried [self.view updateConstraints] and [self.view updateConstraintsIfNeeded] in various places such as viewDidAppear, viewDidLayoutSubviews. Nothing seems to update that topLayoutConstraint.
I am familiar with edge restraints, translucent navigation bar and other various methods of keeping the entire view from appearing under the navigation bar. I do want to keep view full size and I want the translucent bar so these are not solutions for me. It seems the constraints should handle this automatically, hence the "auto" in auto layout.
To simplify, for recreation, UINavigationController with rootViewcontroller showing normal navigation bar with just a title. In viewDidLoad of the next presented viewController I have [self.navigationContoller setPrompt:self.myPrompt]. The view is presented, when the prompt is set, the navigation bar grows larger. Some labels below the bar are set with relation to topLayoutGuide, which places them correctly initially. I expect they would move down when the bar grows. Rotate device back and forth, they now layout correctly. Pop the viewController and push back to top, repeats as above.
So, it turns out it was all me. After trying all manner of forcing layout updates in all sorts of ways, the solution was to move the [myView setPrompt:myPrompt] out of viewDidLoad and call it in viewDidAppear instead.
Works completely as expected. Navbar grows, subviews shift and shrink as needed. Now I have to hunt down all the experimental code I plastered everywhere trying to do it wrong.

Resources