如何在UITextView中找到光标的像素位置? [英] How to find a pixel-positon of a cursor in UITextView?

查看:304
本文介绍了如何在UITextView中找到光标的像素位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为iPad开发一个简单的写作应用程序。

I'm developing a simple writing app for iPad.

我想在 UITextView中计算光标的像素位置

在stackoverflow中,Tony写了一个很好的算法来找到像素位置的光标。

In stackoverflow, Tony wrote one good algorithm to find the pixel-position of the cursor.

Pixel - UITextView中的光标位置

我对此进行了一点修改,它几乎可以提供正确的光标像素位置。

I implemented this with a little modification, and it almost works that it gives the correct pixel-position of the cursor. However, it only works with English alphabets.

如果在行尾有中文或日文字符, UITextView 执行字符包装,而不是文字包装,即使汉字之间没有空格。我认为Tony的算法在 UITextView 只执行单词换行(使用英文字母)时起作用。

If there is Chinese or Japanese character at the end of line, UITextView performs character-wrapping, instead of word-wrapping, even though there is no space between Chinese characters. I think Tony's algorithm works when UITextView performs only word-wrapping (with English alphabets).

UITextView

中找到光标的像素位置的方法或者有一种方法来确定特殊字符跟随字符包装如汉字或包装如英语?

Or is there a way to determine whether a particular character follows character-wrapping like Chinese characters or word-wrapping like English?

添加:

这是我基于Tony算法的实现。我在横向模式中放置一个 UITextView ,所以它的宽度是1024,我使用大小为21的自定义字体。你应该更改 sizeOfContentWidth sizeOfContentLine sizeOfContentWidth 小于实际宽度,且 sizeOfContentLine 大于实际的字体大小(行高>字体大小) 。

Here's my implementation based on Tony's algorithm. I placed one UITextView in a landscape mode, so its width is 1024, and I used the custom font with size 21. You should change sizeOfContentWidth and sizeOfContentLine appropriately. sizeOfContentWidth is smaller than the actual width, and sizeOfContentLine is larger than the actual font size (line height > font size).

对不起,有些杂乱的代码和意见!还有一些小错误,如果在行尾输入中文字符(没有换行),它会给出错误的位置。

Sorry about messy code and comments! There are still some small bugs, and it gives wrong position if you type Chinese characters at the end of line (no word-wrap).

#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);


推荐答案

如果你定位到IOS7, $ b UITextView方法:

If you target to IOS7 only you could use UITextView method:

- (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

这篇关于如何在UITextView中找到光标的像素位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆