user1051372
user1051372

Reputation: 1

CoreText,Copy&Paste

I want use UIMenuController in CoreText,but I can't select the words,I think I must compute the coordinate of the words,but the coordinate can't be correspondence with NSRange.Is there any function to solve it?

Sorry my English is not good~ Here is my code

CFArrayRef lines = CTFrameGetLines(leftFrame);
CFIndex i, total = CFArrayGetCount(lines);


CGFloat y;
for (i = 0; i < total; i++) {
    CGPoint origins;
    CTFrameGetLineOrigins( leftFrame, CFRangeMake(i, 1), &origins);


    CTLineRef line = (CTLineRef)CFArrayGetValueAtIndex(lines, i);

    y = self.bounds.origin.y + self.bounds.size.height - origins.y;

    //CTLineDraw(line, UIGraphicsGetCurrentContext());
    CFArrayRef runs = CTLineGetGlyphRuns(line);
    CFIndex r, runsTotal = CFArrayGetCount(runs);
    //NSLog(@"runsTotal = %d",runsTotal);
    for (r = 0; r < runsTotal; r++) {

        CGRect runBounds = CTRunGetImageBounds(CFArrayGetValueAtIndex(runs, r), context, CFRangeMake(0, 0));

        NSLog(@"runBounds.x = %f,runBounds.y = %f",runBounds.origin.x,runBounds.origin.y);
        CFIndex index =  CTRunGetStringRange(CFArrayGetValueAtIndex(runs, r)).location;

        //NSLog(@"%d",index);

    }
}

Upvotes: 0

Views: 622

Answers (2)

dengApro
dengApro

Reputation: 4008

You can use a tap gesture to get the tap position,

and you have the CTFrame,

Then You can have the needed text frame calculated.


Here is an example , how to calculate two character's frame of the tap position .

pass in CTFrame and Tap Point, get two character's frame and its range in the CTFrame

+(CGRect)parserRectWithPoint:(CGPoint)point range:(NSRange *)selectRange frameRef:(CTFrameRef)frameRef
{
    CFIndex index = -1;
    CGPathRef pathRef = CTFrameGetPath(frameRef);
    CGRect bounds = CGPathGetBoundingBox(pathRef);
    CGRect rect = CGRectZero;
    
    // get lines
    NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frameRef);
    if (!lines) {
        return rect;
    }
    NSInteger lineCount = [lines count];
    // prepare for origins of each line
    CGPoint *origins = malloc(lineCount * sizeof(CGPoint)); 
    if (lineCount) {
        CTFrameGetLineOrigins(frameRef, CFRangeMake(0, 0), origins);
        
        // check tap point in every line
        // found, then break
        for (int i = 0; i<lineCount; i++) {
            CGPoint baselineOrigin = origins[i];
            CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:i];
            CGFloat ascent,descent,linegap; //声明字体的上行高度和下行高度和行距
            CGFloat lineWidth = CTLineGetTypographicBounds(line, &ascent, &descent, &linegap);
            CGRect lineFrame = CGRectMake(baselineOrigin.x, CGRectGetHeight(bounds)-baselineOrigin.y-ascent, lineWidth, ascent+descent+linegap+[LSYReadConfig shareInstance].lineSpace);   
            if (CGRectContainsPoint(lineFrame,point)){
                // line found 
                CFRange stringRange = CTLineGetStringRange(line);
                // glyph found
                index = CTLineGetStringIndexForPosition(line, point);
                CGFloat xStart = CTLineGetOffsetForStringIndex(line, index, NULL);
                CGFloat xEnd;
                // choose two words by default
                if (index > stringRange.location+stringRange.length-2) {
                    xEnd = xStart;
                    xStart = CTLineGetOffsetForStringIndex(line,index-2,NULL);
                    (*selectRange).location = index-2;
                }
                else{
                    xEnd = CTLineGetOffsetForStringIndex(line,index+2,NULL);
                    (*selectRange).location = index;
                }
                // choose two character
                (*selectRange).length = 2;
                rect = CGRectMake(origins[i].x+xStart,baselineOrigin.y-descent,fabs(xStart-xEnd), ascent+descent);
                
                break;
            }
        }
    }
    free(origins);
    return rect;
}

Upvotes: 1

yincan
yincan

Reputation: 478

core-text does not support the text-selection, you need to do it by yourself, please follow the EGOTextView as example

Upvotes: 0

Related Questions