20

I've just found an annoying bug with the new keyboardDismissMode property of the scroll view. When using this with a text view with the value UIScrollViewKeyboardDismissModeInteractive and the keyboard is dismissed the scroll view seems to jump up to the top before it continues to decelerate.

I've filed a bug report with Apple but need a workaround. I've tried the DAKeyboardControl without the new iOS7 support which behind the scenes is using the keyboardDismissMode and it still does it which to me indicates this is a much deeper problem.

Any suggestions?

Romance
  • 1,416
  • 11
  • 21
Dino
  • 566
  • 1
  • 7
  • 19
  • I'm trying to reproduce. I've added a text view over an window, and have a long text. I set the keyboard dismiss mode to interactive. I added a `scrollViewDidScroll:` implementation to catch strange jumps. It works as expected. Could you please elaborate more on your use case? – Léo Natan Sep 26 '13 at 06:45
  • I've posted my example project here: http://cl.ly/013q0t022j0l. The project is a single text view in a storyboard with some lorem ipsum text. The view controller registers for the keyboard did hide notification and is also the text view delegate. I'm logging the did hide notification as well as the y position of the content offset when the scroll view scrolls. – Dino Sep 26 '13 at 10:15
  • If you run the project and dismiss the keyboard you will see some pretty erratic numbers coming from the scrollViewDidScroll method after the did hide notification is fired. – Dino Sep 26 '13 at 10:17
  • This seems to happen whenever i call resignFirstResponder on my UITextView. Interestingly it does not happen when I hide the keyboard with the iPhone 6 Landscape "Hide Keyboard" button. – Obiwahn Oct 08 '14 at 13:47

2 Answers2

1

for this issue better you code with scrollviewDelegete and simply mention when you want dismiss keyboard through ResignFirstResponder

Shri Ram
  • 11
  • 3
0

Does seem to be a bug or just a non-ideal default state. But based on the code in the test project something like the below may work after some finer tuning.

There are two problems with the sample code, one is that you aren't doing anything about the size of the text when the keyboard does appear, so you can't use or see the text under the keyboard. There are other solutions but a quick and dirty solution is to change the frame size (in a submission app I would also grab the animation info and animate the view frame change to match the keyboard animation which is beyond the scope of this question). You do that in 'willShow' or the like, and bring it back in 'didHide' or the like.

Then, the content offset is fudged when its hidden and there does appear to be some strange states while you are dragging it offscreen before and around your callbacks for hiding and scroll view changes. I just save the state and "fix" it once the keyboard goes away and I've updated the text view.

I created a few properties and an outlet in the storyboard to fudge with the text view.

- (void) viewDidLoad
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}

- (void) keyboardWillShow:(NSNotification *)notification
{
    NSDictionary * info = [notification userInfo];
    CGSize size = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGRect rect = self.textView.frame;
    rect.size.height -= size.height;
    self.textView.frame = rect;
}

- (void)keyboardDidHide:(NSNotification *)notification
{
    NSLog(@"====== keyboardDidHide =======");

    NSDictionary * info = [notification userInfo];
    CGSize size = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGRect rect = self.textView.frame;
    rect.size.height += size.height;
    self.textView.frame = rect;


    self.hidingKeyboard = YES;
}

- (void) scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSLog(@"%f", scrollView.contentOffset.y);
    if(self.hidingKeyboard == YES)
    {
        scrollView.contentOffset = self.lastOffset;
        self.hidingKeyboard = NO;
        NSLog(@"====== reset =======");
    }
    else
        self.lastOffset = scrollView.contentOffset;
}
EricLeaf
  • 892
  • 5
  • 12
  • The purpose of the sample code was to demonstrate the bug which is caused by dismissing the keyboard. I appreciate the fact that you cannot view the text behind the keyboard but this has nothing to do with the bug I am asking about. By not including code that changes the frame when the keyboard appears we can rule out the possibility that it is causing/contributing to the problem. – Dino Sep 26 '13 at 19:24
  • Also I've implemented your fix for the messed up content offset after the keyboard hides and it doesn't work even when there is no deceleration. – Dino Sep 26 '13 at 19:36
  • Describe more the interaction you are attempting and what you are seeing. When I drag from the textView over the keyboard down off screen the keyboard pans and the code above keeps the text that I see onscreen at the same location I expect it to be (i.e. i drag it down with the keyboard). – EricLeaf Sep 27 '13 at 13:08
  • If you log the contentOffset.y of the srollview in the scrollViewDidScroll delegate method and then dismiss the keyboard when the jump happen you will see erratic numbers logged in the console. It doesn't happen all the time but it does happen often enough to be a problem. It's most obvious when there is no deceleration in the scroll view when the dismissal happens. – Dino Sep 30 '13 at 14:04