1

UILabel 内の文字の正確な位置を決定しようとしています。

(UILabel *)label.text = @"こんにちは!";

「お」の位置を決めたいです。sizeWithFont を使用して、先行するすべての文字 (または先行する文字列全体) の幅を合計できると考えました。私が取得した幅の値は、本来あるべき値よりも約 10% 大きくなっています。個々の文字の幅を合計すると ([@"H" sizeWithFont...] + [@"e" sizeWithFont...] + l... + l...)、[@"Hell" sizeWithFont よりも多くのエラーが蓄積されます。 ...]。

文字列内の単一のグリフの位置を正確に決定する方法はありますか?

どうもありがとう。

4

3 に答える 3

4

はい。ただし、UILabel ではなく、sizeWithFont: を使用していません。

私は最近 Apple Developer Support と協力しましたが、どうやら sizeWithFont: は実際には近似値です。テキストが (1) 複数の行にまたがって折り返され、(2) 非ラテン文字 (中国語、アラビア語など) が含まれている場合、精度が低下します。どちらも sizeWithFont: でキャプチャされない行間隔の変更を引き起こします。したがって、100% の精度が必要な場合は、この方法に頼らないでください。

できることは次の 2 つです。

(1) UILabel の代わりに、編集不可の UITextView を使用します。これは、UITextInput プロトコル メソッドfirstRectForRange:をサポートします。これを使用して、必要な文字の四角形を取得できます。次のような方法を使用できます。

- (CGRect)rectOfCharacterAtIndex:(NSUInteger)characterIndex inTextView:(UITextView *)textView
{
    // set the beginning position to the index of the character
    UITextPosition *beginningPosition = [textView positionFromPosition:textView.beginningOfDocument offset:characterIndex];
    // set the end position to the index of the character plus 1
    UITextPosition *endPosition = [textView positionFromPosition:beginningPosition offset:1];
    // get the text range between these two positions
    UITextRange *characterTextRange = [textView textRangeFromPosition:beginningPosition toPosition:endPosition]];
    // get the rect of the character
    CGRect rectOfCharacter = [textView firstRectForRange:characterTextRange];
    // return the rect, converted from the text input view (unless you want it to be relative the text input view)
    return [textView convertRect:rectOfCharacter fromView:textView.textInputView];
}

これを使用するには (myTextView という名前の UITextView が既に画面上にあると仮定します)、次のようにします。

myTextView.text = @"Hello!";
CGRect rectOfOCharacter = [self rectOfCharacterAtIndex:4 inTextView:myTextView];
// do whatever you need with rectOfOCharacter

このメソッドは、 1文字の矩形を決定するためにのみ使用してください。この理由は、改行が発生した場合、firstRectForRange: は改行前の最初の行の rect のみを返すためです。

また、上記のメソッドを頻繁に使用する場合は、UITextView カテゴリとして追加することを検討してください。エラー処理を追加することを忘れないでください!

iOS 用 Text, Web, and Editing Programming Guide を読むと、firstRectForRange: が「フードの下」でどのように機能するかについて詳しく知ることができます。

(2) UIView をサブクラス化し、Core Text を使用して文字列をレンダリングすることにより、独自の UILabel を作成します。レンダリングを行っているので、文字の位置を取得できます。このアプローチは大変な作業であり、本当に必要な場合にのみ価値があります (もちろん、私はあなたのアプリの他のニーズを知りません)。これがどのように機能するかわからない場合は、最初のアプローチを使用することをお勧めします。

于 2012-12-07T15:54:51.963 に答える
0

フォントは日々スマートになっており、文字の位置を前の文字と比較して考慮しています。

文字の開始位置の例を次に示しますo

NSRange posRange = [hello rangeOfString:@"o"];
NSString *substring = [hello substringToIndex:posRange.location];
CGSize size = [substring sizeWithFont:[UIFont systemFontOfSize:14.0f]];

いいえ、文字を含む文字列に対して同じことを行い、文字を含まoない文字列で見つかったサイズを差し引くことができますo。これにより、文字とサイズの適切な開始位置が得られるはずです。

于 2012-12-07T15:25:50.007 に答える