Как найти пиксель-положение курсора в UITextView? - PullRequest
6 голосов
/ 13 октября 2010

Я разрабатываю простое приложение для письма для iPad.

Я пытаюсь вычислить позицию курсора в пикселях в UITextView.Я потратил несколько недель на разработку этого, но все еще не мог понять, как это сделать.

В stackoverflow Тони написал один хороший алгоритм для определения положения курсора в пикселях.

Пиксельная позиция курсора в UITextView

Я реализовал это с небольшой модификацией, и это почти работает так, что он дает правильную пиксельную позицию курсора.Тем не менее, он работает только с английскими алфавитами.

Если в конце строки есть китайский или японский символ, UITextView выполняет перенос символов вместо переноса слов, даже если между китайцами нет пробела.персонажи.Я думаю, что алгоритм Тони работает, когда UITextView выполняет только перенос слов (с английскими алфавитами).

Есть ли другой способ найти положение курсора в пикселях в UITextView?

Или есть способ определить, следует ли конкретный символ за переносом символов, как китайские символы, или за переносом слов, как английский?

Добавление:

Вот моя реализация, основанная на алгоритме Тони.Я поместил один UITextView в альбомный режим, поэтому его ширина равна 1024, и я использовал нестандартный шрифт размером 21. Вы должны соответственно изменить sizeOfContentWidth и sizeOfContentLine.sizeOfContentWidth меньше, чем фактическая ширина, а sizeOfContentLine больше, чем фактический размер шрифта (высота строки> размер шрифта).

Извините за грязный код и комментарии!Есть еще небольшие ошибки, и они дают неправильную позицию, если вы вводите китайские символы в конце строки (без переноса слов).

#define sizeOfContentWidth 1010
#define sizeOfContentHeight 1000
#define sizeOfContentLine 25

    // Stores the original position of the cursor
NSRange originalPosition = textView.selectedRange;    

// Computes textView's origin
CGPoint origin = textView.frame.origin;

// Checks whether a character right to the current cursor is a non-space character
unichar c = ' ';

if(textView.selectedRange.location != [textView.text length])
    c = [textView.text characterAtIndex:textView.selectedRange.location];

// If it's a non-space or newline character, then the current cursor moves to the end of that word
if(c != 32 && c != 10){
    NSRange delimiter = [textView.text rangeOfCharacterFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]
                                                       options:NSLiteralSearch
                                                         range:NSMakeRange(textView.selectedRange.location, [textView.text length] - textView.selectedRange.location)];

    if(delimiter.location == NSNotFound){
        delimiter.location = [textView.text length];
    }

    textView.selectedRange = delimiter;
}

// Deviation between the original cursor location and moved location
int deviationLocation = textView.selectedRange .location - originalPosition.location;

// Substrings the part before the cursor position
NSString* head = [textView.text substringToIndex:textView.selectedRange.location];

// Gets the size of this part
CGSize initialSize = [head sizeWithFont:textView.font constrainedToSize:CGSizeMake(sizeOfContentWidth, sizeOfContentHeight)];

// Gets the length of the head
NSUInteger startOfLine = [head length];

// The first line
BOOL isFirstLine = NO;

if(initialSize.height / sizeOfContentLine == 1){
    isFirstLine = YES;
}

while (startOfLine > 0 && isFirstLine == NO) {
    // 1. Adjusts startOfLine to the beginning of the first word before startOfLine
    NSRange delimiter = [head rangeOfCharacterFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] options:NSBackwardsSearch range:NSMakeRange(0, startOfLine)];

    // Updates startsOfLine
    startOfLine = delimiter.location;

    // 2. Check if drawing the substring of head up to startOfLine causes a reduction in height compared to initialSize. 
    NSString *tempHead = [head substringToIndex:startOfLine];

    // Gets the size of this temp head
    CGSize tempHeadSize = [tempHead sizeWithFont:textView.font constrainedToSize:CGSizeMake(sizeOfContentWidth, sizeOfContentHeight)];

    // Counts the line of the original
    int beforeLine = initialSize.height / sizeOfContentLine;

    // Counts the line of the one after processing
    int afterLine = tempHeadSize.height / sizeOfContentLine;

    // 3. If so, then you've identified the start of the line containing the cursor, otherwise keep going.
    if(beforeLine != afterLine)
        break;
}

// Substrings the part after the cursor position
NSString* tail;

if(isFirstLine == NO)
    tail = [head substringFromIndex:(startOfLine + deviationLocation)];
else {
    tail = [head substringToIndex:(startOfLine - deviationLocation)];
}

// Gets the size of this part
CGSize lineSize = [tail sizeWithFont:textView.font forWidth:sizeOfContentWidth lineBreakMode:UILineBreakModeWordWrap];

// Gets the cursor position in coordinate
CGPoint cursor = origin;    
cursor.x += lineSize.width;
cursor.y += initialSize.height - lineSize.height;

// Back to the original position
textView.selectedRange = originalPosition;

// Debug
printf("x: %f,   y: %f\n", cursor.x, cursor.y);

Ответы [ 2 ]

2 голосов
/ 11 ноября 2013

Если вы ориентируетесь только на IOS7, вы можете использовать метод UITextView:

- (CGRect)caretRectForPosition:(UITextPosition *)position;

Краткий пример:

NSRange range; // target location in text that you should get from somewhere, e.g. textview.selectedRange
UITextView textview; // the text view

UITextPosition *start = [textview positionFromPosition:textview.beginningOfDocument offset:range.location];
CGRect caretRect = [self caretRectForPosition:start]; // caret rect in UITextView
0 голосов
/ 30 июня 2011

Это, вероятно, довольно неэффективно, но вы могли бы взять тот же базовый принцип кода, который вы опубликовали, и взять строку текста, на которой находится курсор, и выполнить цикл по каждому отдельному символу и выполнить [NSString sizeWithFont:forWidth:lineBreakMode:] для вычисления ширины каждого символа, и вы могли бы добавить все это для вашей позиции х?Просто идея, но может помочь решить проблему с переносом слов.

...