Мне удалось решить эту проблему (по крайней мере, в большинстве случаев), но это может быть сложно. Получить координату у не так сложно. Подавление ложных сообщений прокрутки, которые система запускает на вашем столе, может быть.
Подход, который я выбрал, выглядит следующим образом:
- в делегате для вашего 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];
}
}