当contentOffset具有值时,Scrollview的位置在动画期间跳转

时间:2011-06-04 22:08:28

标签: iphone objective-c uiscrollview

我正在使用此处找到的TPKeyboardAvoidingScrollView:https://github.com/michaeltyson/TPKeyboardAvoiding

以下是该类的相关代码块:

- (void)keyboardWillShow:(NSNotification*)notification {
if ( !CGRectEqualToRect(priorFrame, CGRectZero) ) return;

UIView *firstResponder = [self findFirstResponderBeneathView:self];
if ( !firstResponder ) {
    // No child view is the first responder - nothing to do here
    return;
}

priorFrame = self.frame;

// Use this view's coordinate system
CGRect keyboardBounds = [self convertRect:[[[notification userInfo] objectForKey:_UIKeyboardFrameEndUserInfoKey] CGRectValue] fromView:nil];
CGRect screenBounds = [self convertRect:[UIScreen mainScreen].bounds fromView:nil];
if ( keyboardBounds.origin.y == 0 ) keyboardBounds.origin = CGPointMake(0, screenBounds.size.height - keyboardBounds.size.height);

CGFloat spaceAboveKeyboard = keyboardBounds.origin.y - self.bounds.origin.y;
CGFloat offset = -1;

CGRect newFrame = self.frame;
newFrame.size.height -= keyboardBounds.size.height - 
                            ((keyboardBounds.origin.y+keyboardBounds.size.height) 
                                - (self.bounds.origin.y+self.bounds.size.height));

CGRect firstResponderFrame = [firstResponder convertRect:firstResponder.bounds toView:self];
if ( firstResponderFrame.origin.y + firstResponderFrame.size.height >= screenBounds.origin.y + screenBounds.size.height - keyboardBounds.size.height ) {
    // Prepare to scroll to make sure the view is above the keyboard
    offset = firstResponderFrame.origin.y + self.contentOffset.y;
    if ( self.contentSize.height - offset < newFrame.size.height ) {
        // Scroll to the bottom
        offset = self.contentSize.height - newFrame.size.height;
    } else {
        if ( firstResponder.bounds.size.height < spaceAboveKeyboard ) {
            // Center vertically if there's room
            offset -= floor((spaceAboveKeyboard-firstResponder.bounds.size.height)/2.0);
        }
        if ( offset + newFrame.size.height > self.contentSize.height ) {
            // Clamp to content size
            offset = self.contentSize.height - newFrame.size.height;
        }
    }
}

// Shrink view's height by the keyboard's height, and scroll to show the text field/view being edited
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]];
self.frame = newFrame;

if ( offset != -1 ) {
    [self setContentOffset:CGPointMake(self.contentOffset.x, offset) animated:YES];
}
[UIView commitAnimations];
}

- (void)keyboardWillHide:(NSNotification*)notification {
if ( CGRectEqualToRect(priorFrame, CGRectZero) ) return;

// Restore dimensions to prior size
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]];
self.frame = priorFrame;
priorFrame = CGRectZero;
[UIView commitAnimations];
}

我遇到一个问题,当键盘开始隐藏时,scrollView会立即跳起来,因此它的原点位于窗口顶部之上。然后它会动画到正确的位置。

我发现只有当contentOffset是&gt;时才会发生这种情况。动画运行时为0。

调试时我注意到当键盘关闭动画开始时内容偏移为54。 我发现如果我将这段代码添加到keyboardWillHide的开头:

priorFrame.size.height -= self.contentOffset;

...然后不会发生跳转并且动画会正常运行,但是scrollView最终会太短。

有什么想法吗?

另请注意,我的scrollView的常规帧是(0,44,320,416),因为它位于标题栏下方。

1 个答案:

答案 0 :(得分:2)

似乎这可能是UIKit中的一个错误,不确定。我通过动画contentInset而不是frame.size.height找到了修复。您可以在我的项目分支http://github.com/wordofchristian/TPKeyboardAvoiding

中看到它