使用CoreTextタッチをクリック行動
-
25-09-2019 - |
質問
しているのか教えてくださいコードのビューを描いても起用CoreText.この思索のためのurlをさせていただきます。その考え方としては、持ち込めないすべてのオーバーヘッド、 UIWebView
だからクリックできるリンクです。ユーザーのタップがリンク(全体ではなくテーブルビュー細胞)でも、たい消防車を委譲方法を表示するのに使用するモーダルビューを含むウェブビューにあるurl。
私のパスの文字列としてのインスタンス変数のビューと、および、コードが起き -drawRect:
(私として簡潔).
私のタッチハンドラが不完全ながら、印刷私が思っています。です。
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
CGContextRef context = UIGraphicsGetCurrentContext();
NSLog(@"attribString = %@", self.attribString);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.attribString);
CTFrameRef ctframe = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, self.attribString.length), attribPath, NULL);
CFArrayRef lines = CTFrameGetLines(ctframe);
for(CFIndex i = 0; i < CFArrayGetCount(lines); i++)
{
CTLineRef line = CFArrayGetValueAtIndex(lines, i);
CGRect lineBounds = CTLineGetImageBounds(line, context);
// Check if tap was on our line
if(CGRectContainsPoint(lineBounds, point))
{
NSLog(@"Tapped line");
CFArrayRef runs = CTLineGetGlyphRuns(line);
for(CFIndex j = 0; j < CFArrayGetCount(runs); j++)
{
CTRunRef run = CFArrayGetValueAtIndex(runs, j);
CFRange urlStringRange = CTRunGetStringRange(run);
CGRect runBounds = CTRunGetImageBounds(run, context, urlStringRange);
if(CGRectContainsPoint(runBounds, point))
{
NSLog(@"Tapped run");
CFIndex* buffer = malloc(sizeof(CFIndex) * urlStringRange.length);
CTRunGetStringIndices(run, urlStringRange, buffer);
// TODO: Map the glyph indices to indexes in the string & Fire the delegate
}
}
}
}
}
で最も美しいコード現在、まだいくので、ご容赦をコードす。
の問題なんであることをタップ外部リンクに何を期待していような出来事が起きないようにとこと:いください。
しかし、私は期待 "Tapped line"
に印刷さいをタップと同じラインのリンクをはっていないが、と私は期待も "Tapped line"
や "Tapped run"
を印刷します。
私は迷ってこれらの資源をいった解像度はこの問題にはココアを具体的にはほぼ完全に適用できないという問題点が)に関する情報が不足していてこの特定の。
私は喜んで受のポインタを文書化する方法について詳細を適切に行に検知した場合に触れた範囲内での中核的テキスト描画以上のコードが、この時点で、どんなこの問題を解決するそれぞよろしくお願い申し上げます。
更新:していま絞っ問題への調整問題です。私は身の座標としてではなく、上記の問題になっているチとして登録い、その座標空間反転させ、ことはできるのか?じです。
解決
私は、タッチ位置から文字列の文字インデックスを取得するには、これを行っています。行番号が、この場合、私のようになります:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touch ended");
UITouch* touch = [touches anyObject];
CGPoint pnt = [touch locationInView:self];
CGPoint reversePoint = CGPointMake(pnt.x, self.frame.size.height-pnt.y);
CFArrayRef lines = CTFrameGetLines(ctFrame);
CGPoint* lineOrigins = malloc(sizeof(CGPoint)*CFArrayGetCount(lines));
CTFrameGetLineOrigins(ctFrame, CFRangeMake(0,0), lineOrigins);
for(CFIndex i = 0; i < CFArrayGetCount(lines); i++)
{
CTLineRef line = CFArrayGetValueAtIndex(lines, i);
CGPoint origin = lineOrigins[i];
if (reversePoint.y > origin.y) {
NSInteger index = CTLineGetStringIndexForPosition(line, reversePoint);
NSLog(@"index %d", index);
break;
}
}
free(lineOrigins);
}
他のヒント
あなたは、CALayerのにあなたのテキスト描画を追加しようと、あなたのtouchesEndedで、それに対して自分の意見層のサブレイヤとして、この新しいレイヤーを追加し、hittestだろうか?その場合、あなたが描かれたテキストよりも大きい層を作ることによって、より大きな触れる面積を作成することができる必要があります。
// hittesting
UITouch *touch = [[event allTouches] anyObject];
touchedLayer = (CALayer *)[self.layer hitTest:[touch locationInView:self]];
ニック・H247の答えのスウィフト3バージョン:
var ctFrame: CTFrame?
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first, let ctFrame = self.ctFrame else { return }
let pnt = touch.location(in: self.view)
let reversePoint = CGPoint(x: pnt.x, y: self.frame.height - pnt.y)
let lines = CTFrameGetLines(ctFrame) as [AnyObject] as! [CTLine]
var lineOrigins = [CGPoint](repeating: .zero, count: lines.count)
CTFrameGetLineOrigins(ctFrame, CFRange(location: 0, length: 0), &lineOrigins)
for (i, line) in lines.enumerated() {
let origin = lineOrigins[i]
if reversePoint.y > origin.y {
let index = CTLineGetStringIndexForPosition(line, reversePoint)
print("index \(index)")
break
}
}
}