2016-04-07 15 views
1

私は、円形または楕円形の領域の中央にテキストを描画するように取り組んでいます。理想的には、テキストを縦と横の中央に配置したいが、それは自然に領域の境界に流れるようにする。不規則な形のUITextViewでテキストを垂直にセンタリングする

UITextViewNSTextContainerの除外パスを使用して、特定の垂直オフセットで、テキストを水平に中央に配置する(下のコードを参照)ようにするアプローチが見つかりました。しかし、私はどのように垂直センタリングを達成するか分からない。

私が見てきたアプローチは、テキストが配置され、最終的な高さがわかった後にテキストビューのcontentInsetを調整することを提案しています。 (たとえば、this question)ただし、不規則な形の領域の場合、配置された後のテキストの高さは、領域レイアウトがどこから始まるかによって異なります。

私が検討したアプローチは、満足のいくレイアウトが達成されるまでレイアウトプロセスを再試行することです。誰かがこのようなアプローチで成功したのですか?ここでの課題の1つは、すべてのテキストがビュー内でレンダリングされているかどうか(すなわち、すべてのテキストをレイアウトするのに十分なスペースがあるかどうか)を判断する方法を研究していないことです。 UITextViewを使用しているときに 'レンダリング'されていますか?

最後に、これはテキストを表示するためのものです。ユーザーがビューの内容を編集できるようにする必要はありません。この場合、CoreTextはおそらくより良いアプローチになりますか?

私はiOS開発にはかなり新しいので、私がやっていることが何か面白かったら、それも知っておくと便利です!

ありがとうございます!役立つ場合

let boundingRect = CGRect(...) 
let textView = UITextView(frame: boundingRect) 

textView.editable = false 
view.addSubview(textView) 

let verticalInset:CGFloat = <some value> 

let width = boundingRect.width 
let height = boundingRect.height 
let textBounds = CGSize(width: width, height:height - 2*verticalInset) 
textView.bounds = textBounds 

let exclusionRect = CGRect(x:0, y:-verticalInset, width:width, height:height) 

let textRegion = UIBezierPath(ovalInRect: exclusionRect)  
let exclusionPath = UIBezierPath(rect:exclusionRect) 
exclusionPath.appendPath(textRegion.bezierPathByReversingPath()) 

textView.textContainer.exclusionPaths = [exclusionPath] 

let paragraphStyle = NSMutableParagraphStyle() 
paragraphStyle.alignment = .Center 

let attributes = [NSParagraphStyleAttributeName: paragraphStyle] 
let formattedContent = NSAttributedString(string: "....", attributes:attributes) 

textView.attributedText(formattedContent) 

ここで上記を視覚化するのに役立つ画像は、です: example

+0

これは私が現在取り組もうとしているものです。私はTextKitが唯一の方法かもしれないと思っています。 –

答えて

0

私はここに幻想的な答えを提供することはできません。

しかし、私はちょうどYYTextを試しました。これには、垂直方向のテキストアライメントと除外パスをサポートする "YYLabel"があります。 Demoプロジェクト、具体的にはその実例を示すtableviewの 'TextAttributes1'行を見てみましょう。

+0

@Christopherの提案に感謝します。私はそれをチェックします。実際には、私もusecaseのための実行可能な解決策を見つけ出すことができました。乾杯! – duncanm

+0

Oop - 追加する必要があります:私はYYTextをチェックアウトする機会があったあなたの答えをマークします。 – duncanm

1

テキストを矩形領域にレイアウトする場合は、後で上下に移動することで縦方向にセンタリングするのが簡単です。あなたの場合のように、領域が長方形ではない場合、これは不可能です。なぜなら、テキストを縦方向にシフトした後に必ずしもその形状に収まるとは限らないからです。

私はこれに対する解決策は常に反復的な方法だと考えています。たとえば、インセットが増えているシェイプのテキストをレンダリングし、テキストが結果のシェイプに収まるように最大のインセットを見つけます。文字列全体がレンダリングされているかどうかをチェックすることができ、このframe

let text:NSAttributedString = ... // The text to render 
let path:CGPath = ... // Bounds the shape in which the text is rendered 
let framesetter = CTFramesetterCreateWithAttributedString(text) 
let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, nil) 

コア・テキストでこれを行うには、次のようなテキストレイアウトのためのCTFrameを作成することができます

let range = CTFrameGetVisibleStringRange(frame) 
if text.length == range.length { 
    // Fits 
} 
あなたの場合は

let ctx:CGContext = ... 
CTFrameDraw(renderFrame, ctx) 

:テキストをレンダリングする

そして、レンダリングされたテキストの詳細が必要な場合はCTFrameGetLinesを使用してCTLineframeから取得できます。次にCTFrameGetLineOriginsCTLineGetBoundsWithOptionsをオプションUseGlyphPathBoundsまたはUseOpticalBoundsと組み合わせて使用​​すると、単一行の光学的境界を計算できます。これにより、より正確な垂直方向の調整が可能になります。 (CoreTextをCoreGraphicsで直接使用するために必要な座標系の変換は、ちょっと面倒なことがあります。

関連する問題