iPhone:将表格视图单元格滚动到可见的自定义键盘对齐工具栏上方?

时间:2009-07-12 19:02:35

标签: iphone objective-c uitableview user-interface scroll

在过去的几天里,我一直在询问a question或两个人正在开发一个应用程序,该应用程序使自定义工具栏与iPhone键盘的顶部对齐。我正在使用Josh在this question中描述的方法;基本上,我让视图控制器监听UIKeyboardWillShowNotification并根据需要添加工具栏。

视图控制器本身管理一个表格视图,其单元格都包含UITextField。显示的键盘和工具栏正在编辑这些文本字段。我仍然遇到的唯一问题是:当键盘和工具栏显示为一个单元格大约在桌子的一半左右时,它会滚动显示在键盘上方,但不在工具栏上方

单元格和文本字段仍可编辑,但大约一半的单元格隐藏在工具栏下。如果我在工具栏中消失(不要将其添加到通知响应器中),整个单元格将变为可见,但显然我将丢失工具栏提供的功能。

有没有办法更改文本字段滚动到的位置?我尝试过使用UITableView方法scrollToRowAtIndexPath:atScrollPosition:animated:,但是当切换到几个单元格时,它往往会产生奇怪的结果。

将表格视图单元格滚动到自定义键盘工具栏上方的可见位置的最佳方法是什么?

4 个答案:

答案 0 :(得分:17)

我完全按照你在我的应用中描述的内容。这是我使用的代码,逐字逐句。这是非常好的动画,似乎工作得非常好。

两个免责声明:

  1. 我将parentView作为自定义初始化的一部分传递。
  2. 我没有写这个代码,我不赞成它。我是从Matt Gallagher真正精彩的博客Cocoa With Love获得的。

  3. static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
    static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
    static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
    // adjust this following value to account for the height of your toolbar, too
    static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
    
    
    - (void)textFieldDidEndEditing:(UITextField *)textField
    {
      CGRect viewFrame = self.parentView.frame;
      viewFrame.origin.y += animatedDistance;
    
      [UIView beginAnimations:nil context:NULL];
      [UIView setAnimationBeginsFromCurrentState:YES];
      [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
    
      [self.parentView setFrame:viewFrame];
    
      [UIView commitAnimations];
    }
    
    - (void) textFieldDidBeginEditing:(UITextField*) textField {
      CGRect textFieldRect = [self.parentView.window convertRect:textField.bounds fromView:textField];
      CGRect viewRect = [self.parentView.window convertRect:self.parentView.bounds fromView:self.parentView];
      CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
      CGFloat numerator = midline - viewRect.origin.y - MINIMUM_SCROLL_FRACTION * viewRect.size.height;
      CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION) * viewRect.size.height;
      CGFloat heightFraction = numerator / denominator;
    
      if (heightFraction < 0.0) {
        heightFraction = 0.0;
      }else if (heightFraction > 1.0) {
        heightFraction = 1.0;
      }
    
      animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
    
      CGRect viewFrame = self.parentView.frame;
      viewFrame.origin.y -= animatedDistance;
    
      [UIView beginAnimations:nil context:NULL];
      [UIView setAnimationBeginsFromCurrentState:YES];
      [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
    
      [self.parentView setFrame:viewFrame];
    
      [UIView commitAnimations];
    }
    

答案 1 :(得分:6)

假设您知道将在键盘上方显示的 NSIndexPath ,您可以使用以下快速而干净的方法:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    UITableViewCell *aCell = [myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:6 inSection:0]];
    CGSize cellSize = aCell.frame.size;
    [myTableView setContentOffset:CGPointMake(0, cellSize.height*6) animated:YES];
}       

- (void)textFieldDidEndEditing:(UITextField *)textField {
    [myTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] 
                       atScrollPosition:UITableViewScrollPositionTop 
                               animated:YES];
}

由于 UITableView 继承自 UIScrollView ,您可以调整 contentOffset 属性以反映其中的行可见性你有兴趣。

DidEndEditing 方法中,您必须恢复原始滚动位置。这是通过标准的 scrollToRowAtIndexPath:atScrollPosition:animated 调用来实现的。

答案 2 :(得分:0)

也许您可以将UITableView的大小调整为导航栏和键盘上方工具栏之间的高度,然后将该行滚动到视图中?

答案 3 :(得分:0)

由于所有UITableView也都是UIScrollView,因此您可以调用它们上的所有标准滚动方法。

这样的事情会:

- (void)scrollTableView:(UITableView *)tableView toIndexPath:(NSIndexPath *)indexPath withBottomPadding:(CGFloat)bottomPadding
{
    CGRect rectForRow = [tableView rectForRowAtIndexPath:indexPath];
    CGRect bounds = [tableView bounds];
    CGPoint contentOffset = [tableView contentSize];
    if (rectForRow.origin.y + rectForRow.size.height > contentOffset.y + bounds.size.height - bottomPadding)
        [tableView setContentOffset:rectForRow.origin.y + rectForRow.size.height - bounds.size.height - bottomPadding animated:YES];
    else
        [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
}

注意:我目前不在使用Xcode的Mac。我将

时测试此代码