iOS 7中的UITableView在编辑UITableViewCell中的UITextView时无法滚动到正确位置

10

我有一个包含静态单元格的表视图。其中一个单元格包含一个UITextView,并动态计算heightForRowAtIndexPath:,使得该单元格始终足够高以容纳文本(在iOS 7下需要一些工作,因为不再能简单地询问textView的contentSize)。

当我点击文本框以开始编辑时,键盘会动画进入,tableView上的contentInsets会自动调整以考虑此情况(即,iPhone竖屏方向的底部插入216px),光标变为可见,然后表视图滚动到其他位置。最终看起来像反弹。

这是模拟器中的视频:https://www.dropbox.com/s/htdbb0t7985u6n4/textview-bounce.mov

请注意,光标在键盘上方只停留了一秒钟。我已经记录了表视图的contentOffset,我可以看到它滚动到一个不错的值,然后突然“掉头”并回滚。

奇怪的是,如果我在模拟器中启用慢速动画,则问题会消失;contentOffset的反转不会发生,事情会按照我预期的方式工作(即iOS 6行为)。

这是慢动画的视频:https://www.dropbox.com/s/nhn7vspx86t4exb/textview-nobounce.mov

实现说明:

  • 文本框是粉色的,具有AutoLayout约束,将其固定在单元格上0距离(除了左侧,即10pt)
  • 我使用boundingRectWithSize:来计算tableView的高度,调整lineFragmentPadding和任何顶部/底部插入。看起来没问题。
  • 我已将textView设置为不可滚动,但当scrollEnabled == YES时,没有注意到任何不同之处。
  • 这是一个表视图控制器,automaticallyAdjustsScrollViewInsets == YES。

  • 1
    我有完全相同的问题,我已经追踪到UITableView的contentSize在我进行UITableView beginupdates和endupdates之后被重置了。 - perrohunter
    1个回答

    3
    在键盘出现时尝试调整UITableView的框架。在viewWillAppear中调用[self attachKeyboardHelper],在viewWillDisappear中调用[self detachKeyboardHelper]。请注意保留HTML标记,但不要提供解释。
    - (void)attachKeyboardHelper{
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillAppear:)
                                                     name:UIKeyboardWillShowNotification
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillHide:)
                                                     name:UIKeyboardWillHideNotification
                                                   object:nil];
    }
    
    - (void)detachKeyboardHelper{
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    - (void)keyboardWillAppear:(NSNotification *)notification{
        NSDictionary* userInfo = [notification userInfo];
    
        NSTimeInterval animationDuration;
        UIViewAnimationCurve animationCurve;
        CGRect keyboardEndFrame;
    
        [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
        [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
        [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
    
        // Animate up or down
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:animationDuration];
    
        CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
        if(self.view==self.tableView){
            CGRect newTableFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.view.bounds.size.height-keyboardFrame.size.height);
            self.tableView.frame = newTableFrame;
        }else{
            CGRect newTableFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.view.bounds.size.height-self.tableView.frame.origin.y-keyboardFrame.size.height);
            self.tableView.frame = newTableFrame;
        }
    
        [UIView commitAnimations];
    }
    
    - (void)keyboardWillHide:(NSNotification *)notification{
        NSDictionary* userInfo = [notification userInfo];
    
        NSTimeInterval animationDuration;
        UIViewAnimationCurve animationCurve;
        CGRect keyboardEndFrame;
    
        [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
        [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
        [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
    
    
        CGRect newTableFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.view.superview.bounds.size.height-self.tableView.frame.origin.y);
        self.tableView.frame = newTableFrame;
        if(newTableFrame.size.height>self.tableView.contentSize.height-self.tableView.contentOffset.y){
            float newOffset=MAX(self.tableView.contentSize.height-newTableFrame.size.height, 0);
            [self.tableView setContentOffset:CGPointMake(0, newOffset) animated:YES];
        }
    
    }
    

    答案加上了一些示例,变得更好了。对于试图在这里找到答案的新手来说非常有帮助;-) - Johan Karlsson

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接