有没有办法在UITextView中获取光标(闪烁条)的位置(CGPoint)(相对于其内容更可取)。我不是说NSRange的位置。我需要一些东西:
- (CGPoint)cursorPosition;
它应该是非私有的API方式。
答案 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;
}