view considers navigation bar only after rotation - ios

I have a simple UIScrollView
UIScrollView *mainScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
[self.view addSubview:mainScrollView];
[mainScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
When the view is loaded and shown, part of UIScrollView appears under the navigation bar. But after rotation the view is suddenly considers navigation bar and pins the view to its bottom.
How can I make a view consider navigation bar from the beginning?

To start UIScrollView at bottom of UINavigationBar then i would suggest you to set Adjust Scroll View Insets property and setting Extend Edges property as well. do the needful changes of below property as per your requirement.

Ok, I solved this issue.
Problem has been solved by moving creation of scrollView to viewDidLoad method. Somehow, if scrollView is created outside the "load" methods, we can face such kind of problems.

Related

InputAccessoryView covers the bottom bar

Any idea how to get an inputAccessoryView to anchor to the tab bar rather than the bottom of the screen?
I have created a UIViewController and overridden the following methods:
-(BOOL)canBecomeFirstResponder {
return YES;
}
-(UIView *)inputAccessoryView {
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, 44);
self.keyboardInputAccessoryView =[[BRKeyboardInputBarView alloc] initWithFrame:frame leftButtonTitle:#"Left" andRightButtonTitle:#"Send"];
[self.keyboardInputAccessoryView setDelegate:self];
[self.keyboardInputAccessoryView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.keyboardInputAccessoryView removeFromSuperview];
return self.keyboardInputAccessoryView;
}
View controller with inputAccessoryView covering the tab bar
By the looks of it the view controller adds the view to the window rather than the current view controllers view, which would explain its positioning. However if I remove the line:
[self.keyboardInputAccessoryView removeFromSuperview];
I get a crash when I tap in the textview of my accessory view:
The view hierarchy is not prepared for the constraint:<NSLayoutConstraint:0x7fa0c2ca5f80 BRKeyboardInputBarView:0x7fa0c2d6fad0.bottom == UIInputSetContainerView:0x7fa0c295a2c0.bottom>
So I guess what I am asking is what is the correct way to add a keyboard accessory view so that it plays nicely with auto layout and avoids the crash, but also anchors itself to the view and not the window?
What you are seeing is the right behaviour.
The results you are seeing is because of the fact that UIViewController is a UIResponder subclass. By overriding the inputAccessoryView and returning an instance of a view, UIViewController will take care of placing that view at the bottom of the screen and animating it appropriately when keyboard appears or disappears.
If you want to add this bar on top of your keyboard, then you need to set the property inputAccessoryView of a textField/textView to your custom view.

iOS - Animations inside Navigation Bar doesn't work

I have a scenario where I needed to add an animation inside the Navigation Bar, but the simulator doesn't animate. I add a UIView, add a label/text field and create outlets for the constraints and update them with "UIView animateWithDuration:" Instead, the simulator just updates the constraints and displays the view accordingly, but without any animation. I have tried it by modifying both constraints as well as frames (separately).
[self.view layoutIfNeeded];
[UIView animateWithDuration: 3
delay: 0.0
options: UIViewAnimationOptionCurveEaseInOut
animations: ^{
self.constraint.constant += 60;
NSLog(#"inside animation");
[self.view layoutIfNeeded];
}
completion:nil];
This is shown when I increment the width constraint by "60" in viewDidLoad: . And it comes out non-animated.
When I configure the constraints (increment width by "60") through a button click, even a static updation doesn't happen.
The same code works perfectly outside the navigation bar inside the UIView, though.
Appreciate any help...
If your navigation bar contains some animation, then you could try out drawing custom navigation bar. Here's what you've to do :
In your view controller in viewDidLoad() method add the following code
self.navigationController.navigationBarHidden = YES;
After that using a UIView create a custom navigation bar with frame adjusted to be visible and top.
After that add components on the view and start working with animations.
You can achieve that by taking custom UIView and create width NSLayoutConstraint outlet to it and in code you can handle the constant property of this variable by calling UpdateConstraintsIfNeeded or UpdateViewConstraints method before calling animation code
Ok, I've solved this at last. Phew...
What I did was...
Added a view in place of barButtonItem (let's call this "superView") and over it another view (and let's call this "subView") so that I get the following configuration.
Constraints were set between subView and objects on top of it. Now, I created outlets (superView and subView) for superView and subView, made them transparent (optional, of course).
Useful note: Set the superView's width to the default bar button item's width and the subView's to the screen width. Disable "Clip Subviews" on superView but enable on the subView.
Added animations as needed where I had wanted, but layoutIfNeeded on the "superView", not the parent view.
[self.superView layoutIfNeeded];
Good luck.

In-call status bar pushes UIPageViewController content view down

I am using a UIPageViewController. When the in-call status bar is toggled while in this view, it adjusts fine. If the in-call status bar is open before the UIPageViewController is loaded, the page gets pushed down by 20pt and a black bar is shown in that space.
Here's a screenshot of what this looks like:
Other posts recommend using setting automaticallyAdjustsScrollViewInsets on the page controller to NO. I've already tried that and it does not work. I've also tried self.edgesForExtendedLayout = UIRectEdgeNone;
Setting the origin of the UIPageViewController frame to 0 works, but feels wrong:
CGRect frame = self.pageController.view.frame;
frame.origin.y = 0;
self.pageController.view.frame = frame;
I ended up resolving this by ensuring the right constraints were on my view controller's main view. Here is an example where I am adding a view controller's view as a subview to a root view controller and then using Masonry (https://github.com/SnapKit/Masonry) to establish constraints that will snap all the child view controller's main view's edges to the root view controller (which itself already has autoresizing masks in place from Interface Builder). This resolved my issue of the status bar leaving that black space because it was pushing this view down (rather than re-sizing):
[self.view addSubview:viewController.view];
[viewController.view mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
In your case, and I don't have your full code so I don't know for sure but something like:
[self.pageController.view mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.pageController.view.superview);
}];
.. ought to do the trick.

How do I position UITableView programmatically while using iOS7's UINavigationBar?

I have a quite regular UIViewController that is a part of a UINavigationController-hierarchy, which naturally makes the view have a UINavigationBar at the top. As we all know, iOS7's navigation bars are very different from previous versions.
If I drag a UITableView into my view in Storyboard, then the 'frame' for the table view is covering the entire view (I.E [tableView setFrame:self.view.frame];). Even behind the NavigationBar.
This makes so that if I scroll, the content will be faintly visible through the bar.
Contrary to most people, I actually like this.
In my current view controller, I would like to create the UITableView programmatically and place it as a subview here. However, I am unable to achieve the same effect this way.
I have tried
UITableView *table = [[UITableView alloc] initWithFrame:self.view.frame];
[self.view addSubview: table];
This makes the 'top scrolling point' stay behind the navigation bar. Imagine a single cell in a tableView, and it's faintly visible through the top bar. If I scroll down, it pops right up behind it. That's the default 'top position'.
I have also tried
CGRect frame = CGRectMake(0, 'nav.y+nav.height', self...width, self...height-y);
UITableView *table = [[UITableView alloc] initWithFrame:frame];
[self.view addSubview: table];
to simply place the table view in the rect below the UINavigationBar, but then I won't get the scrolling transparency effect behind the bar.
I also tried the first example along with this:
[tableView setContentOffset:CGPointMake(0, 'below navbar')];
which makes it stay exactly where I want it to stay, but as soon as I touch it (scroll and release), it scrolls back up behind the navigation bar, and stays there.
What's the programmatic solution to achieve this effect? Do I have to set the offset every time I scroll too far up, or is there a simpler solution? Along with this iOS7-style, I'd imagine they would add something like [tableView setVisibleFrame:] or something..?
Add the table in storyboard like normal but make sure you have it connected to an outlet (we will call it _tableView for now).
Then in your view controller's -viewDidLoad set the top inset to be the status bar plus the navigation bar:
`self.tableView.contentInset = UIEdgeInsetsMake( (self.navigationController.navigationBar.frame.origin.y + self.navigationController.navigationBar.frame.size.height), 0, 0, 0);'
This will make sure that all of the cells will be visible but will also fill the area behind the navigation bar with white so the bar doesn't end up gray.

iOS7 Custom ViewController transition and Top Layout Guide

I implemented a custom UIViewController Transition in my App, which replaces the navigation controllers built in push animation.
Everything works so far, except the toplayoutguide in the newly pushed view controller is 0 although the new view controller inherited the navigation bar from the old view controller.
It should be 64.0 (Statusbar height + Navigation bar height), where it is 0.0 now.
So all objects, which are attached to the top layout guide in the storyboard now appear 64 points too high (below the translucent bar).
When I disable the custom View Transition the top layout guide will have the expected value.
I tried to call layoutSubviews and updateConstraints "all over the place". In the view controller as well as in the navigationcontroller.
As I understand the navigationcontroller (parentviewcontroller) should update the toplayoutguide of the new view controller, but apparently I am missing something in my custom transitioning code, which triggers the update to the correct value for the toplayoutguide.
Here's my custom transition code which is an object set as delegate of the navigationcontroller:
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.7;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIView *animationContainerView = [transitionContext containerView];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *toView = [toVC view];
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIView *fromView = [fromVC view];
CGRect endFrame = [transitionContext finalFrameForViewController:toVC];
CGRect startFrame;
startFrame = CGRectOffset(endFrame, 0, endFrame.size.height);
if (self.operation == UINavigationControllerOperationPop) {
[animationContainerView insertSubview:toView belowSubview:fromView];
[toView setFrame:endFrame];
}
else{
[toView setFrame:startFrame];
[animationContainerView insertSubview:toView aboveSubview:fromView];
}
[UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 usingSpringWithDamping:0.7 initialSpringVelocity:0.8 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
if (self.operation == UINavigationControllerOperationPop) {
[fromView setFrame:startFrame];
[fromView layoutIfNeeded];
}
else{
[toView setFrame:endFrame];
[toView layoutIfNeeded];
}
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
Nothing really fancy happens there. Just the view sliding from the bottom up with some built in dynamics.
The problem is, that the objects attached to the top layout guide now are under the navigation bar, as the top layout guide length == 0.
I can't figure out what I need to do, so that the view controller's toplayoutguide is set to the correct value.
The push navigation is performed "plain vanilla" with a push storyboard segue. All I do, before calling performSegueWithIdentifier is to set the navigationcontrollers delegate.
Here's the code:
self.navigationController.delegate = [[My_CustomNavigationTransitionDelegate alloc] init];
[self performSegueWithIdentifier:#"infosSegue" sender:nil];
What do I miss?
I was having an issue where the bottomLayoutGuide property would set itself to zero length and then would cause my buttons above the tab bar to fall below to tab bar with the autolayout.
Have you looked at doing this
[self.navigationController.view setNeedsLayout]
I put it into my viewwillappear and I stopped getting a zero length on the bottomLayoutGuide property. Maybe that would help you out with your topLayoutGuide property too.
I was able to work around this, with the following view hierarchy:
UIView
UIScrollView
<content, constrained to UIScrollView>
Constrain the UIScrollView to match the UIView's top, leading, trailing, and bottom edges. Interface Builder might want you to use the topLayoutGuide and bottomLayoutGuide for the UIScrollView, or it might not. Maybe it's dependent on the version of Xcode, but some of our View Controllers used the superview, others used the layout guides.
For the views where Interface Builder didn't want to constraint the scroll view relative to its superview, I opened the storyboard in a text editor and adjusted the constraints on the scroll view by hand.
Finally, on the View Controller, make sure that extend edges under top bar is YES, and so is Adjust Scroll View Insets.
Basically, I'm avoiding using the topLayoutGuide, and instead relying on the scroll view insets, which does work.
Where I didn't have a UIScrollView in the hierarchy, like you, NOT extending edges under the top bar worked for me.
I ran into the exact same problem. My custom navigation controller's container view didn't have constraints. The minute I added vertical spacing constraints from the container view to its superview's layout guides (albeit the two were identical in size), and set the top/bottom/status bar appearance on the container view everything was ok and the layout guides of the pushed controllers were in the correct position. Hope that helps.
Update: From the official documentation on topLayoutGuide
A view controller within a container view controller does not set this property's value. Instead, the container view controller constrains the value to indicate:
The bottom of the navigation bar, if a navigation bar is visible
The bottom of the status bar, if only a status bar is visible
The top edge of the view controller’s view, if neither a status bar nor navigation bar is visible
So the container view needs to implement correct constraints and hide/show bars and such for the effects to work. AFAIK there is no API to do this in custom container view controllers.
I found a way. First uncheck "Extend Edges" property of controller after that navigation bar will get in dark color. Add a view to controller and set top and bottom LayoutConstraint -100. Then make view's clipsubview property no (for navigaionbar transculent effect). My english is bad sorry for that. :)

Resources