Положение пикселя курсора в UITextView

Есть ли способ получить положение (CGPoint) курсора (мигающая панель) в UITextView (предпочтительный относительно его содержания). Я не имею в виду местоположение как NSRange. Мне нужно что-то вокруг:

- (CGPoint)cursorPosition;

Это должен быть нечастный API путь.

24
задан Suragch 30 January 2016 в 05:28
поделиться

3 ответа

Это неприятно, но для этого можно использовать UIStringDrawing дополнения к NSString . Вот общий алгоритм, который я использовал:

CGPoint origin = textView.frame.origin;
NSString* head = [textView.text substringToIndex:textView.selectedRange.location];
CGSize initialSize = [head sizeWithFont:textView.font constrainedToSize:textView.contentSize];
NSUInteger startOfLine = [head length];
while (startOfLine > 0) {
    /*
     * 1. Adjust startOfLine to the beginning of the first word before startOfLine
     * 2. Check if drawing the substring of head up to startOfLine causes a reduction in height compared to initialSize.
     * 3. If so, then you've identified the start of the line containing the cursor, otherwise keep going.
     */
}
NSString* tail = [head substringFromIndex:startOfLine];
CGSize lineSize = [tail sizeWithFont:textView.font forWidth:textView.contentSize.width lineBreakMode:UILineBreakModeWordWrap];
CGPoint cursor = origin;
cursor.x += lineSize.width;
cursor.y += initialSize.height - lineSize.height;
return cursor;
}

Я использовал [NSCharacterSet whitespaceAndNewlineCharacterSet] , чтобы найти границы слов.

Это также можно сделать (предположительно более эффективно) с помощью CTFrameSetter в CoreText , но это недоступно в iPhone OS 3.1.3, поэтому, если вы ориентируетесь на iPhone вам нужно будет придерживаться UIStringDrawing .

10
ответ дан 28 November 2019 в 22:29
поделиться

Да - например, есть способ получить позицию курсора. Просто используйте

CGRect caretRect = [textView rectContainingCaretSelection];
return caretRect.origin;

Нет - так как в этом методе частный. Для этого нет общедоступного API.

3
ответ дан 28 November 2019 в 22:29
поделиться

Я пытаюсь отметить выделенный текст, т.е. я получаю NSRange и хочу нарисовать желтый прямоугольник позади этого текста. Есть другой способ?

Я могу посоветовать вам одну хитрость:

NSRange selectedRange = myTextView.selectedRange;
[myTextView select:self];
UIMenuController* sharedMenu = [UIMenuController sharedMenuController];
CGRect menuFrame = [sharedMenu menuFrame];
[sharedMenu setMenuVisible:NO];
myTextView.selectedRange = selectedRange

Используя этот код, вы можете узнать позицию меню вырезать / скопировать / вставить и поместить туда желтый прямоугольник.

Я не нашел способа получить позицию меню без принудительного ее отображения с помощью имитации операции выбора.

С уважением Assayag

1
ответ дан 28 November 2019 в 22:29
поделиться