Пиксельная позиция курсора в UITextView
Есть ли способ получить позицию (CGPoint) курсора (мигающую панель) в UITextView (предпочтительнее относительно его содержимого). Я не имею в виду местоположение как NSRange. Мне нужно что-то вокруг:
- (CGPoint)cursorPosition;
Он должен быть не-частным способом API.
Ответы
Ответ 1
Это больно, но вы можете использовать дополнения 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
.
Ответ 2
Требуется iOS 5
CGPoint cursorPosition = [textview caretRectForPosition:textview.selectedTextRange.start].origin;
Не забудьте проверить, что selectedTextRange
не nil
перед вызовом этого метода. Вы также должны использовать selectedTextRange.empty
, чтобы проверить, что это позиция курсора, а не начало текстового диапазона. Итак:
if (textview.selectedTextRange.empty) {
// get cursor position and do stuff ...
}
Ответ 3
Да - как есть метод для получения позиции курсора. Просто используйте
CGRect caretRect = [textView rectContainingCaretSelection];
return caretRect.origin;
Нет - как в этом методе является приватным. Для этого нет общедоступного API.
Ответ 4
Я пытаюсь выделить выделенный текст, т.е. получаю NSRange и хочу нарисовать желтый прямоугольник за этим текстом. Есть ли другой способ?
Я могу посоветовать вам трюк:
NSRange selectedRange = myTextView.selectedRange;
[myTextView select:self];
UIMenuController* sharedMenu = [UIMenuController sharedMenuController];
CGRect menuFrame = [sharedMenu menuFrame];
[sharedMenu setMenuVisible:NO];
myTextView.selectedRange = selectedRange
Используя этот код, вы можете узнать, как выбрать меню вырезания/копирования/прошлого и разместить желтый прямоугольник.
Я не нашел способ получить положение меню без принуждения, чтобы оно отображалось с помощью моделируемой операции выбора.
Отношения
Assayag
Ответ 5
Сделайте снимок экрана UITextView, затем найдите данные пикселя для цветов, соответствующих цвету курсора.
-(CGPoint)positionOfCursorForTextView:(UITextView)textView {
//get CGImage from textView
UIGraphicsBeginImageContext(textView.bounds.size);
[textView.layer renderInContext:UIGraphicsGetCurrentContext()];
CGImageRef textImageRef = UIGraphicsGetImageFromCurrentImageContext().CGImage;
UIGraphicsEndImageContext();
//get raw pixel data
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
uint8_t * textBuffer = (uint8_t*)malloc(Width * Height * 4);
NSUInteger bytesPerRow = 4 * Width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(textBuffer, Width, Height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, Width, Height), textImageRef);
CGContextRelease(context);
//search
for(int y = 0; y < Height; y++)
{
for(int x = 0; x < Width * 4; x += 4)
{
int red = textBuffer[y * 4 * (NSInteger)Width + x];
int green = textBuffer[y * 4 * (NSInteger)Width + x + 1];
int blue = textBuffer[y * 4 * (NSInteger)Width + x + 2];
int alpha = textBuffer[y * 4 * (NSInteger)Width + x + 3];
if(COLOR IS CLOSE TO COLOR OF CURSOR)
{
free(textBuffer);
CGImageRelease(textImageRef);
return CGPointMake(x/4, y);
}
}
}
free(textBuffer);
CGImageRelease(textImageRef);
return CGPointZero;
}