2011-03-07 57 views
0

我在UITableView单元格内使用UITextView。我为UITextView禁用了滚动功能。当用户键入时,我有逻辑来自动增长UITextView和UITableView单元格。我也有逻辑来自动滚动UITableView并保持新键入的文本可见。我通过调用[tableView scrollRectToVisible:animated:]来做到这一点,只要光标位于文本的最后,这一切都可以正常工作,因为我只需滚动到结尾(tableView.contentSize.height)即可。在UITableViewCell中不可滚动的UITextView - 如何确定游标的y坐标

问题来了,当用户决定将光标放在文本的其他地方(比如在他们的块的中间),然后再次开始输入。此时,我不能再保留新输入的文本,因为我无法确定光标所在的y坐标。

任何帮助将不胜感激!

回答

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]; 
    } 
} 
+0

谢谢,我会尝试一些你的技巧,看看会发生什么...... – bpatrick100 2011-03-08 04:07:38

0

其实有更简单的方法来做到这一点:)

只需添加一个隐藏的UITextView并反映在隐藏的一个主要的文本视图的所有更改。隐藏的文本视图应该有一个固定的高度,所以它会自动滚动更改contentOffset属性。 contentOffset正是你计算光标垂直位置所需要的。

Goog luck!

1

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

这里的想法(我测试了它和作品):

  • 创建附配UITextView(_auxTextView)

  • 落实textViewDidChange委托正文视图。

表视图控制器应通过滚动使用scrollRectToVisible与所述给定偏移表视图实现cellDidChange。确切的计算会减少案件的数量,但重要的是要调用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); 
    } 
相关问题