2010-10-13 32 views
6

Tôi đang phát triển một ứng dụng viết đơn giản cho iPad.Cách tìm pixel-positon của con trỏ trong UITextView?

Tôi đang cố tính toán vị trí pixel của con trỏ trong UITextView. Tôi dành một vài tuần để thiết kế này, nhưng tôi vẫn không thể tìm ra để làm điều đó.

Trong ngăn xếp chồng, Tony đã viết một thuật toán tốt để tìm vị trí pixel của con trỏ.

Pixel-Position of Cursor in UITextView

tôi thực hiện điều này với một chút sửa đổi, và nó gần như làm việc mà nó mang lại cho các pixel đúng vị trí của con trỏ. Tuy nhiên, nó chỉ hoạt động với bảng chữ cái tiếng Anh.

Nếu có ký tự Trung Quốc hoặc Nhật Bản ở cuối dòng, UITextView thực hiện ký tự gói, thay vì gói từ, mặc dù không có khoảng cách giữa các ký tự tiếng Trung. Tôi nghĩ thuật toán của Tony hoạt động khi UITextView chỉ thực hiện việc gói từ (với bảng chữ cái tiếng Anh).

Có cách nào khác để tìm vị trí pixel của con trỏ trong UITextView không?

Hoặc có cách nào để xác định xem một ký tự cụ thể có tuân theo ký tự gói như ký tự tiếng Trung hoặc từ gói như tiếng Anh không?

Bổ sung:

Đây là triển khai của tôi dựa trên thuật toán của Tony. Tôi đặt một UITextView ở chế độ ngang, vì vậy chiều rộng của nó là 1024 và tôi đã sử dụng phông chữ tùy chỉnh có kích thước 21. Bạn nên thay đổi sizeOfContentWidthsizeOfContentLine một cách thích hợp. sizeOfContentWidth nhỏ hơn chiều rộng thực tế và sizeOfContentLine lớn hơn kích thước phông chữ thực tế (chiều cao dòng> kích thước phông chữ).

Xin lỗi về mã lộn xộn và nhận xét! Vẫn còn một số lỗi nhỏ, và nó cho vị trí sai nếu bạn gõ ký tự Trung Quốc vào cuối dòng (không có từ bọc).

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

Ông có thể chia sẻ những thay đổi bạn thực hiện cho Tony, như tôi chắc chắn nhiều người khác đang tìm kiếm câu trả lời về cách tìm vị trí pixel của dấu mũ/con trỏ. Cảm ơn. – Joshua

+0

Xin chào, tôi đã thêm triển khai của mình dựa trên thuật toán của Tony. Một bổ sung cho thuật toán của Tony là lúc đầu, tôi đã di chuyển con trỏ hiện tại đến cuối từ. – pnmn

+0

Thuật toán này dựa trên giả định rằng UITextView chỉ làm từ gói. Tôi nghĩ chúng ta cần một cách tiếp cận khác để tính toán đúng vị trí pixel của con trỏ để làm cho nó hoạt động với bất kỳ loại ký tự nào.Một giải pháp là chúng ta có thể tạo ra chế độ xem văn bản tùy chỉnh hoàn toàn mới bằng cách sử dụng CoreText, UITextInput và UIKeyInput từ đầu, nhưng tôi không muốn làm điều đó chỉ cho một vị trí con trỏ. – pnmn

Trả lời

0

Đây có lẽ là khá hiệu quả, nhưng bạn có thể mất hiệu trưởng cùng cơ bản của mã bạn đã gửi và lấy dòng văn bản con trỏ đang bật, và vòng lặp qua từng nhân vật cá nhân và làm [NSString sizeWithFont:forWidth:lineBreakMode:] để tính toán mỗi chiều rộng của ký tự và bạn có thể thêm tất cả những thứ đó cho vị trí x của bạn? Chỉ là một ý tưởng, nhưng có thể giúp khắc phục vấn đề với gói từ.

2

Nếu bạn nhắm mục tiêu đến iOS7 duy nhất mà bạn có thể sử dụng phương pháp UITextView:

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

mẫu ngắn:

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 
Các vấn đề liên quan