0

I have a screen within an iPhone app that consist of a UITextView. This text view is contained within a UIScrollView. The purpose of the screen is for the user to type in text, and to optionally attach an image to what he is writing. Therefore, the screen also has a UIToolbar with a camera button at the bottom of the screen. The structure of the screen is as follows:

-View
--UIScrollView
---UITextView
--UIToolbar
---UIButton

When the user navigates to this screen, the viewDidAppear method assigns first responder to the uitextview element, so the keyboard shows up, which hides the toolbar and the camera button.

I would like the entire toolbar to re-draw itself right above the keyboard, and to position itself again at the bottom of the screen when the keyboard hides.

I have found related posts on SO (like this one). However, such methods introduce undesired behaviours. For example, implementing the solution in the article above, the toolbar does move with the keyboard, but the UIScrollView gets its frame.origin.y coordinate shifted way above the top of the screen, so it's impossible for the user to see what he is typing.

I have also tried to reset the frame of the toolbar, by adding it as an IBOutlet and using cgrectmake to reposition it. However, after several tries, the toolbar remains stuck at the bottom of the screen and hidden by the keyboard:

- (void) liftMainViewWhenKeybordAppears:(NSNotification*)aNotification{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:0.3];
    [UIView setAnimationCurve:<#(UIViewAnimationCurve)#>]

    CGRect frame = self.keyboardToolbar.frame;
    frame.origin.y = self.keyboardToolbar.frame.origin.y - 280;
    self.keyboardToolbar.frame = frame;

    [UIView commitAnimations];
}

I have tried several iterations similar to the code above and they all fail at repositioning the toolbar.

So in short, what is the right way to float a toolbar right on top of a keyboard in a screen whose space is completely utilised by a uitextview element?

Community
  • 1
  • 1
Luis Delgado
  • 3,644
  • 4
  • 34
  • 54
  • Adjusting frames in iOS8 is not ideal as it conflicts with constraints. Have you tried adding a constraint from the bottom of the toolbar to the superview? You can CTRL frag this into your code and then change the constraint in code when you bring up the editor. So add a height constraint which is 0, drag that into an IBOutlet in your code, when you bring the editor up change the `.constant` field of the IBOutlet to the height of the keyboard. Set back to 0 when the keyboard is dropped. You may need to force a layout. – Rory McKinnel Jun 02 '15 at 09:54
  • 1
    Same idea, but using a spacer view: http://effortlesscode.com/auto-layout-keyboard-shown-hidden/ – Rory McKinnel Jun 02 '15 at 10:02
  • @RoryMcKinnel worked great, thanks for the pointer. I had trouble to translate this code from Swift to Obj-C, but it did the trick. – Luis Delgado Jun 02 '15 at 12:40

1 Answers1

0

Thanks to RoryMcKinnel for the pointer. As the article referenced is in Swift, I thought I might paste the solution that worked for be on ObjC

- (void)keyboardWillShowNotification:(NSNotification *)notification{
NSDictionary *userInfo = notification.userInfo;

double animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardEndFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect convertedKeyboardFrame = [self.view convertRect:keyboardEndFrame fromView:self.view.window];
UIViewAnimationOptions rawAnimationCurve = (UIViewAnimationOptions)[userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
_toolBarBottomGuide.constant = CGRectGetMaxY(self.view.bounds) - CGRectGetMinY(convertedKeyboardFrame);
[UIView animateWithDuration:animationDuration delay:0.0 options:rawAnimationCurve animations:^{
    [self.view layoutIfNeeded];
} completion:nil];
}

Bear in mind, this code did make the toolbar move as required, but the toolbar was not visible at all. It turned out that it was being hidden behind the UIScrollView. This was easily fixed by shifting the order between the scroll view and the toolbar element in the IB hierarchy.

The method above works for the keyboardWillShow event. You'll need to add the corresponding one for when the keyboard hides, like this:

- (void)keyboardWillHideNotification:(NSNotification *)notification{
    NSDictionary *userInfo = notification.userInfo;

    double animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardEndFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    UIViewAnimationOptions rawAnimationCurve = (UIViewAnimationOptions)[userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
    _toolBarBottomGuide.constant = 0.0f;
    [UIView animateWithDuration:animationDuration delay:0.0 options:rawAnimationCurve animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];
}
Luis Delgado
  • 3,644
  • 4
  • 34
  • 54