View moves down when keyboard appears - ios

I'm building an iPad app and there is something weird going on with the top edge of the view in relation to the status bar when the keyboard appears.
The view has a view with a segmented controller at the top with a container view below. When a button in the segmented controller is selected, the view in the container view changes.
I've done some research into the matter (it's definitely iOS 7 related) and have not found any kind of fix. I tried setting edgesForExtendedLayout to UIRectEdgeNone but that does not seem to have any effect. Even more strange, the view only moves half way to its original position when the keyboard dismisses. Any suggestions? I included screenshots below.
Original:
When keyboard appears:
After keyboard dismisses:

I can only assume your code is doing something to move the view when the keyboard appears then later disappears. So you state your view is a UIViewcontroller subclass (implying no contentOffset property). Log the values of the following before and after the keyboard action - one of them must have changed: contentInset, bounds, frame. Knowing which one will assist you in finding the problem.

Related

Can I have UIView shown at bottom of the screen and keyboard presented on top of it when needed?

I would like to have either custom UIView or UIToolbar or inputAccessoryView always visible at the bottom of the screen and not being covered by keyboard when one is presented.
Also keyboard should be visible, meaning it should be presented on top of that view and dismissed accordingly.
It would be nice to have that view as part of the UIViewController, but if it can be part of keyboard it is also acceptable as I have an idea how to achieve the visual impression of it being a part of UIViewController and always visible.
I've run into answers explaining how to add custom toolbar docked at the bottom and shown on top of keyboard once presented.
I've also run into posts explaining how to create a custom keyboard.
There are also some stating keyboard can't be positioned otherwise than docked at the bottom.
I understand if Apple is forcing consistency, but having that view always visible would keep consistency across my app. Therefore, if the final answer is it's not possible, I would appreciate firm explanation or link to apple's mention of this issue, cause I wasn't able to find one so far.
Thanks a lot!

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.

UIScrollView works on 4-inch, doesn't respond to any touch on 3.5-inch

I have a strange problem where I have a scroll view on one of my views that works perfectly on 4-inch devices, both in simulator and actual device. That same scroll view (and views inside it) doesn't respond to any touch event (both tap and scroll) in 3.5-inch devices (same iOS version, 7.0.3). It renders/displays perfectly though. I've even tried to add a tap handler to the view itself directly to see if it will hit (categoriesScrollView is my view):
//viewDidLoad:
UITapGestureRecognizer *test = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(test)];
[categoriesScrollView addGestureRecognizer:test];
-(void)test{
NSLog(#"test");
}
It doesn't hit. Inside the view there are buttons, that can be tapped perfectly on an 4-inch device. This problem occurs both on device and simulator. The first thing that I checked was any device/screensize-specific code, but there isn't any. The second thing I've checked is the layout constraints: Maybe the scrollview's actual bounds was getting smaller (maybe even zero) on 3.5 inch device, but I've checked the frames and everything is normal (the scroll view has clipsToBounds set to YES anyway, so if this was the case, the content would be invisible anyway).
All the other views inside the same view other than this scroll view and its subviews are receiving touch/running perfectly normal. I can't think of anything else, what can be causing this?
I've solved the problem. I've first put another button somewhere inside the main view on top of the scroll view (but scroll view was inside another container, top bar), the button worked. I've then moved the button inside the same container with scroll view (on top of it), and it didn't work where alarm bells rang for me. Apparently, I had a progress indicator and that indicator was centered in the main below with top constraint to the top bar. Top bar had clipsToBounds set no NO and the indicator was pushing the size of the top bar to almost zero, making the scroll view draw but not respond to touch. It was a simple autolayout issue, and the top bar which contains the scroll view didn't clip the scroll view out of it's bounds, which made the bug harder to find.

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.

Why are touches not detected at top of screen with status bar hidden?

In our app, we show modal windows that take up the whole screen, and we hide the status bar at this time. However, buttons placed at the top of the screen have reduced hit areas: their tops do not detect touches. This is true of custom buttons and buttons in the navigation controller.
What is preventing detection of those touches?
FYI: I have two other windows, a HUD view and a status bar overlay, and both are hidden. I've tried putting the status bar overlay behind the main window, as well. Problem remains.
Update: This problem is caused, at least in some cases, by hiding the status bar while still having a scroll view with scrollsToTop set to YES. Although I have found a case where the problem remains even after disabling scrollsToTop for all resident scroll views. (I wrote a simple method to walk the view hierarchy to find all scroll views and report their current scrollsToTop setting.)

Resources