2

「ボブがあなたの写真を気に入った」などの NSMutableAttributedString があります。

「Bob」と「picture」に 2 つの異なるタップ イベントを追加できないかと考えています。理想的には、「Bob」をタップすると、Bob のプロフィールを含む新しいビュー コントローラーが表示され、「写真」をタップすると、写真を含む新しいビュー コントローラーが表示されます。NSMutableAttributedString でこれを行うことはできますか?

4

2 に答える 2

10

これは、CoreTextを使用して、ユーザーが選択/タッチした文字のインデックスを取得するメソッドを実装することで実現できます。まず、CoreTextを使用して、カスタムUIViewサブクラスに属性付き文字列を描画します。オーバーライドされたメソッドの例drawRect:

- (void) drawRect:(CGRect)rect
{
    // Flip the coordinate system as CoreText's origin starts in the lower left corner
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextTranslateCTM(context, 0.0f, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0f, -1.0f);

    UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.bounds];
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge   CFAttributedStringRef)(_attributedString));

    if(textFrame != nil) {
        CFRelease(textFrame);
    }

    // Keep the text frame around.
    textFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path.CGPath, NULL);
    CFRetain(textFrame);

    CTFrameDraw(textFrame, context);
}

次に、テキストを調べて特定のポイントの文字インデックスを見つけるメソッドを作成します。

- (int) indexAtPoint:(CGPoint)point
{
    // Flip the point because the coordinate system is flipped.
    point = CGPointMake(point.x, CGRectGetMaxY(self.bounds) - point.y);
    NSArray *lines = (__bridge NSArray *) (CTFrameGetLines(textFrame));

    CGPoint origins[lines.count];
    CTFrameGetLineOrigins(textFrame, CFRangeMake(0, lines.count), origins);

    for(int i = 0; i < lines.count; i++) {
        if(point.y > origins[i].y) {
            CTLineRef line = (__bridge CTLineRef)([lines objectAtIndex:i]);
            return CTLineGetStringIndexForPosition(line, point);
        }
    }

    return 0;
}

最後に、メソッドをオーバーライドしてtouchesBegan:withEvent:、ユーザーが触れた場所の場所を取得し、それを文字のインデックスまたは範囲に変換できます。

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *t = [touches anyObject];
    CGPoint tp = [t locationInView:self];
    int index = [self indexAtPoint:tp];

    NSLog(@"Character touched : %d", index);
}

そのメモリはARCによって管理されていないため、必ずCoreTextをプロジェクトに含め、保持しているリソース(テキストフレームなど)をクリーンアップしてください。

于 2013-03-18T18:48:04.833 に答える
1

私がそれを処理する方法は、標準を使用することNSStringですUITextView。次に、UITextInputプロトコル方式を利用しますfirstRectForRange:。次に、その四角形に目に見えないものを簡単にオーバーレイし、UIButton実行したいアクションを処理できます。

于 2013-03-18T18:12:41.820 に答える