UITableViewCell中不可滚动的UITextView - 如何确定光标y坐标

时间:2011-03-07 19:38:51

标签: iphone sdk uitableview cursor uitextview

我在UITableView单元格中使用UITextView。我为UITextView禁用了滚动功能。当用户输入时,我有逻辑来自动增长UITextView和UITableView单元格。我也有逻辑来自动滚动UITableView并保持新键入的文本可见。我这样做是通过调用[tableView scrollRectToVisible:animated:]这一切正常,只要光标位于文本的最末端,因为我只需滚动到结尾(tableView.contentSize.height)。

当用户决定将光标定位在文本的其他位置(例如在其块的中间)时,问题就出现了,并再次开始输入。此时,我无法再将新键入的文本保留在视图中,因为我无法确定光标所在的y坐标。

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:1)

好的,我终于实现了它并且更容易,你不需要像我之前说过的那样使用contentOffset,它有效,但有一些意想不到的问题。诀窍是使用辅助UITextView来计算光标上方文本的高度。

这个想法(我测试过并且有效):

  • 创建辅助UITextView(_auxTextView)

  • 为主文本视图实现textViewDidChange委托。

表视图控制器应通过使用给定偏移量的cellDidChange滚动表视图来实现scrollRectToVisible。确切的计算取决于案例,但重要的是调用beginUpdateendUpdate以强制更新应该基于属性rowHeight的行高。

以下是代码的一部分(抱歉,我无法发布实际代码,因为它位于一个大的上下文中)。

    -(void)textViewDidChange:(UITextView *)textView {
      if(_prevHeight != self.textHeight) {
        _prevHeight = self.textHeight;
        NSRange range;
        range.location = 0;
        range.length = textView.selectedRange.location;
        NSString *str = [_textView.text substringWithRange:range];
        _auxTextView.text = str;
        [delegate cellDidChange:self offset:_auxTextView.contentSize.height];
      }
    }

   -(CGFloat)rowHeight {
      return self.textHeight + somePadding;
    }

   -(CGFloat)textHeight {
     return fmaxf(_textView.contentSize.height, someMinimumHeight);
   }

答案 1 :(得分:0)

我设法解决了这类问题(至少在大多数情况下),但这可能很棘手。获得y坐标并不是那么难。抑制系统在您的桌面触发的杂散滚动消息可以是。

我采取的方法是这样的:

  • 在UITextView的委托中实现textViewDidChangeSelection:
  • 从textView和selectedRange
  • 获取文本
  • 您可能需要检查所选范围是否>文字长度(有时它可以;如果你认为它不可能,你可能会得到奇怪的崩溃......我做了)
  • 截断字符串,以便从开头到选择点获取字符串
  • 为该长度的字符串计算UITextView的高度。使用类似的东西:

    textHeight = [workingString sizeWithFont:[self screenFont] constrainedToSize:CGSizeMake([self editWidth] -16.0,CGFLOAT_MAX)]。height;

  • -16.0对于补偿默认边框非常重要。我用16.0取得了很好的成绩,但没有记录。可能有更好的方法来计算补偿,但我还没有解决。

  • 此时我手动滚动tableView。它是UIScrollView的子类,因此响应setContentOffset:但是,为了使所有内容顺利运行,我将UITableView分类并有时忽略contentOffset:和contentOffset:animated:messages。系统会生成这些,有时会在您不需要它们时生成。 (这就是我所说的'棘手')。

可能有一种更简单的方法来实现这一目标。希望如此。如果是这样,有人会发布它。

这是我的应用程序中的一些(稍微丑陋)代码(仍在进行中)。它使用我的应用程序中的一些其他类/类别,但希望您可以随时了解正在发生的事情。这可能与您的问题不太匹配,但希望这有一些用处。

- (void) textViewDidChangeSelection: (UITextView *)textView;
{
    if (!checkSelectionVisible) return; // bail most of the time
    checkSelectionVisible = NO; // this is a one off

    EditController* theEditController = [self editController];
    ParagraftTableView* theTableView = (ParagraftTableView*)[theEditController tableView];

    ParagraphCell* currentCell = (ParagraphCell*) [theTableView cellForRowAtIndexPath: [NSIndexPath indexPathForRow:[self paragraphNumber] inSection:0]];

    CGPoint cellOrigin = currentCell.origin;
    CGPoint contentOffset = [theTableView contentOffset];
    NSRange selectedRange = [textView selectedRange];
    NSString* text = [textView text];
    if (selectedRange.location > [text length])
    {
        selectedRange.location = 0; // of out of bounds set to start
        NSLog(@"In textViewDidChangeSelection - selection out of bounds. Setting to start of paragraph.");
    }

    CGFloat textHeight = [[Formats shared] heightForText: [text substringToIndex: selectedRange.location]]; 

    if ((cellOrigin.y + textHeight) > ([theTableView height]+ [theTableView contentOffset].y))
    {
        NSLog(@"Selection point is off screen. Scroll into view.");

        CGFloat txHeight = [[[Formats shared] screenFont] pointSize];
        CGFloat newOffset = cellOrigin.y + textHeight - ([theTableView height] - 3*txHeight);
        contentOffset.y = newOffset;

        [theTableView setContentOffset:contentOffset];
    }
}

答案 2 :(得分:0)

实际上有一种更简单的方法:)

只需添加隐藏的UITextView并镜像对隐藏的主文本视图所做的所有更改。隐藏文本视图应具有固定高度,因此它将自动滚动以更改contentOffset属性。而contentOffset正是您计算光标垂直位置所需的。

Goog运气好!