UITextView中光标的像素位置

时间:2010-04-13 21:32:19

标签: iphone objective-c uitextview

有没有办法在UITextView中获取光标(闪烁条)的位置(CGPoint)(相对于其内容更可取)。我不是说NSRange的位置。我需要一些东西:

- (CGPoint)cursorPosition;

它应该是非私有的API方式。

6 个答案:

答案 0 :(得分:50)

需要iOS 5

CGPoint cursorPosition = [textview caretRectForPosition:textview.selectedTextRange.start].origin;

在调用此方法之前,请务必检查selectedTextRange是否为nil。您还应该使用selectedTextRange.empty来检查它是光标位置而不是文本范围的开头。所以:

if (textview.selectedTextRange.empty) {
    // get cursor position and do stuff ...
}

答案 1 :(得分:10)

这很痛苦,但您可以使用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 :(得分:5)

SWIFT 4 版本:

if let cursorPosition = textView.selectedTextRange?.start {
    // cursorPosition is a UITextPosition object describing position in the text (text-wise description)

    let caretPositionRectangle: CGRect = textView.caretRect(for: cursorPosition)
    // now use either the whole rectangle, or its origin (caretPositionRectangle.origin)
}

textView.selectedTextRange?.start返回光标的文本位置,然后我们只需使用textView.caretRect(for:)将其像素位置设为textView

答案 3 :(得分:3)

是 - 因为有一种获取光标位置的方法。只需使用

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

否 - 因为此方法是私有的。这没有公共API。

答案 4 :(得分:1)

  

我尝试标记选定的文本,即我收到一个NSRange,并希望在该文本后面绘制一个黄色矩形。还有另外一种方法吗?

我可以告诉你一些技巧:

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

使用此代码,您可以知道剪切/复制/过去菜单的位置,并放置黄色矩形。

我找不到通过模拟选择操作强制显示菜单位置的方法。

此致 Assayag

答案 5 :(得分:1)

获取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;
}