-scrollRangeToVisible:在iOS 7中不考虑键盘大小

Jef*_*wen 7 objective-c uitextview ios ios7

我一直在视图控制器中使用以下代码来更新键盘显示时UITextView的内容偏移量:

- (void)keyboardWasShown:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];
    CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    UIEdgeInsets contentInsets = UIEdgeInsetsMake( 0.0, 0.0, keyboardRect.size.height, 0.0 );
    self.textView.contentInset = contentInsets;
    self.textView.scrollIndicatorInsets = contentInsets;
}
Run Code Online (Sandbox Code Playgroud)

在键盘显示的情况下,手动将UITextView的内容滚动到底部,使其正确地在键盘顶部正上方结束. - [UITexView scrollRangeToVisible:]但是,似乎不再考虑键盘的存在.

  • 在iOS 6中,文本视图会滚动,直到键盘上方显示指定的范围.
  • 在iOS 7中,可见性现在似乎基于文本视图的框架而不是以前的内容插入.因此视图将仅在范围延伸到框架下方时滚动,然后它将仅滚动到足以使该范围在底部可见

在视觉上,这是正在发生的事情.我建立了一个内联搜索我的文本视图与控件在结果之间跳转(类似于在Safari中搜索).因此,在此处显示的文本视图,当用户点击"下一步"按钮时,搜索结果将逐渐显示结果.当用户转到第七个结果时,视图将滚动直到可见.

当用户转到第五个搜索结果时,使用键盘(来自UISearchBar)在相同的搜索结果上,它将滚动到键盘上方.但仅限于iOS 6.在iOS 7中,在非键盘情况下转到第七个搜索结果之前不会发生滚动,即使这样,它也会滚动相同的数量,因此它只能在文本视图框架的底部下方看到.

这是iOS 7中的已知变化吗?我正在使用自动布局,所以我要尝试的另一件事是调整文本视图的底部间距约束以缩小整个视图以避免问题,但是想要检查是否仍然可以使用我现有的代码IOS 7.

Iva*_*chi 5

虽然已经回答了这个问题,但是在构建我自己的UITextView子类时会遇到同样的问题(如果你感兴趣的话,可以在我的GitHub上找到它),并提出了该scrollRangeToVisible:方法的自定义实现.所有你需要做的是调整contentInsetscrollIndicatorInset你的属性UITextView如你已经做(相关答案休闲的Google阅读本),然后调用:

[textView scrollRangeToVisible:range consideringInsets:YES];
Run Code Online (Sandbox Code Playgroud)

我将相关代码包装在一个类别中,其中还有一些其他有用的方法来解释iOS 7中的insets:

注意:由于我在子类中组织此代码的方式,您需要它们.随意根据自己的喜好重新组织.

@interface UITextView (insets)

// Scrolls to visible range, eventually considering insets
- (void)scrollRangeToVisible:(NSRange)range consideringInsets:(BOOL)considerInsets;

// Scrolls to visible rect, eventually considering insets
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated consideringInsets:(BOOL)considerInsets;

// Returns visible rect, eventually considering insets
- (CGRect)visibleRectConsideringInsets:(BOOL)considerInsets;

@end

@implementation UITextView (insets)

// Scrolls to visible range, eventually considering insets
- (void)scrollRangeToVisible:(NSRange)range consideringInsets:(BOOL)considerInsets
{
    if (considerInsets && (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1))
    {
        // Calculates rect for range
        UITextPosition *startPosition = [self positionFromPosition:self.beginningOfDocument offset:range.location];
        UITextPosition *endPosition = [self positionFromPosition:startPosition offset:range.length];
        UITextRange *textRange = [self textRangeFromPosition:startPosition toPosition:endPosition];
        CGRect rect = [self firstRectForRange:textRange];

        // Scrolls to visible rect
        [self scrollRectToVisible:rect animated:YES consideringInsets:YES];
    }
    else
        [self scrollRangeToVisible:range];
}

// Scrolls to visible rect, eventually considering insets
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated consideringInsets:(BOOL)considerInsets
{
    if (considerInsets && (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1))
    {
        // Gets bounds and calculates visible rect
        CGRect bounds = self.bounds;
        UIEdgeInsets contentInset = self.contentInset;
        CGRect visibleRect = [self visibleRectConsideringInsets:YES];

        // Do not scroll if rect is on screen
        if (!CGRectContainsRect(visibleRect, rect))
        {
            CGPoint contentOffset = self.contentOffset;
            // Calculates new contentOffset
            if (rect.origin.y < visibleRect.origin.y)
                // rect precedes bounds, scroll up
                contentOffset.y = rect.origin.y - contentInset.top;
            else
                // rect follows bounds, scroll down
                contentOffset.y = rect.origin.y + contentInset.bottom + rect.size.height - bounds.size.height;
            [self setContentOffset:contentOffset animated:animated];
        }
    }
    else
        [self scrollRectToVisible:rect animated:animated];
}

// Returns visible rect, eventually considering insets
- (CGRect)visibleRectConsideringInsets:(BOOL)considerInsets
{
    CGRect bounds = self.bounds;
    if (considerInsets)
    {
        UIEdgeInsets contentInset = self.contentInset;
        CGRect visibleRect = self.bounds;
        visibleRect.origin.x += contentInset.left;
        visibleRect.origin.y += contentInset.top;
        visibleRect.size.width -= (contentInset.left + contentInset.right);
        visibleRect.size.height -= (contentInset.top + contentInset.bottom);
        return visibleRect;
    }
    return bounds;
}

@end
Run Code Online (Sandbox Code Playgroud)