web-dev-qa-db-ja.com

SwiftでiOS用の縦書きのテキストUILabelとUITextViewを作成するにはどうすればよいですか?

タイトルに基づいてこの質問に来たが、モンゴル語に興味がない場合は、代わりにこのQ&Aを探している可能性があります。


私はSwiftを習得して、 伝統的なモンゴル語 のiOSアプリを開発しています。問題は、伝統的なモンゴル語が上から下、左から右に垂直に書かれています。私の質問は、テキストを垂直に表示し、それでも行の折り返し機能を維持するにはどうすればよいですか?

私と一緒に1分間滞在する場合は、問題をより明確に説明します。以下は、私が実現したいテキストビューのイメージです。外国のスクリプトがあなたを捨てる場合に備えて、私は同じパターンに従う英語のテキストを含めました。実際、アプリに表示する英語のテキストがある場合、このようになります。

enter image description here

シンプルな1行のUILabelの場合、時計回りに90度回転すると機能します。ただし、複数行のUITextViewの場合、行の折り返しを処理する必要があります。単純な90度回転だけを行うと、最初に書かれたのは最終行になります。

これまでのところ、この問題を克服できると思う計画を立てました。

  1. すべての文字が垂直にミラーリングされたカスタムフォントを作成します。
  2. テキストビューを時計回りに90度回転します。
  3. テキストビューを水平にミラーリングします。

enter image description here

これでテキストの折り返しが処理されます。

ミラーリングされたフォントができます。ただし、UITextViewの回転とミラーリングのSwiftコーディングを行う方法がわかりません。ソリューションの一部にヒントを与えると思われる次のリンクを見つけましたが、それらはすべてObjective Cにあり、Swiftにはありません。

アプリストアには thisthis などの伝統的なモンゴルのアプリがあります)しかし、ソースコードを共有している人をまだ見つけていないので、テキストを表示するために舞台裏で何をしているのかわかりません。私は、伝統的なモンゴル語を読む数百万人向けのアプリを他の人が開発するのがそれほど難しくないように、自分のコードをオープンソースにする予定です。あなたがこの努力に与えることができるどんな援助でも、私だけでなくモンゴル人たちにも大いに感謝されます。自分がわからない場合でも、この質問を投票して見やすくすることは役立ちます。

更新

@sangonzの回答は今でも素晴らしい回答ですが、すべてを機能させることができなかったため、一時的に承認済みの回答のマークを外しました。具体的には:

  • スクロールを有効にする(カスタムビューをscrollviewに埋め込むか、または subclassing UIScrollView によって)。 githubプロジェクトでは、@ sangonzはこれは簡単だと言っていましたが、私には向いていませんでした。
  • 方向変更時にWord行の(ストレッチではなく)再レイアウトを取得します。これは、もう少し調査して解決するのは難しくないはずです。
  • テキスト行がビューの端まで達していないのはなぜですか?底に大きな隙間があります。
  • カスタム垂直ビューのNSTextStorageを他のUITextViewからリンク解除する方法。この質問を参照してください

この時点まで 私は元の方法を使用してきました 上記で提案しましたが、私が本当に望んでいるのは、@ sangonzが提案したもののようなものを動作させることです。

私は現在、次のような代替方法も検討しています

46
Suragch

編集:これが私がやっとやった方法です。

これが私のGitHubの非常に基本的な実装です: Vertical-Text-iOS

特別なことは何もありませんが、うまくいきます。最後に、TextKitと画像処理を組み合わせる必要がありました。コードを見てください。それには以下が含まれます:

  1. NSTextContainerをサブクラス化して、適切なテキスト寸法を取得します。
  2. カスタムUIViewを作成して、各行にアフィン変換を適用してテキストをレンダリングし、NSLayoutManagerを使用してレンダリングして、すべてのTextKit機能を保持します。

TextKitの方法

すべてのネイティブテキストの利点(ハイライト、選択など)を維持する適切な方法は、標準のTextKit APIを使用することです。あなたが提案している方法は、それらすべてを壊すか、または奇妙な行動をもたらす可能性があります。

ただし、iOSのTextKitはそのままでは垂直方向をサポートしていないようですが、そのために準備されています。補足として、OS Xでは多少サポートされており、textView.setLayoutOrientation(.Vertical)を呼び出すことができますが、それでもいくつかの制限があります。

NSTextLayoutOrientationProviderプロトコルは、明示的なNSVerticalGlyphFormAttributeName属性がない場合に、適合オブジェクトに配置されるテキストのデフォルトの向きを提供するインターフェースを定義します。このインターフェイスを実装する唯一のUIKitクラスはNSTextContainerであり、そのデフォルトの実装はNSTextLayoutOrientationHorizontalを返します。縦書きテキストを処理するNSTextContainerサブクラスは、このプロパティをNSTextLayoutOrientationVerticalに設定して、カスタムレイアウト方向ロジックをサポートできます。

出典: IKit> NSTextLayoutOrientationProvider iOSのプロトコルリファレンス

結論としてNSTextContainerのサブクラス化を開始する必要があり、NSLayoutManagerNSTextContainer たくさん。


カスタム画像処理方法

一方、カスタムテキストレンダリングに従うことにした場合は、次の方法をお勧めします。

  1. 通常のテキストを通常のフォントで非表示レイヤーにレンダリングします。境界ボックスに正しいサイズを指定します。
  2. テキストのプロパティ、主にテキストの高さと行間隔を取得します。
  3. 画像を処理します下の画像にあるように、各線を下から上に逆順に描画します。結果として、新しいCGImageを取得するはずです。
  4. 画像を回転させてUIImageを作成し、正しいUIImageOrientation値を設定します。
  5. その画像UIScrollViewに挿入して、水平スクロールのみを許可します。

このメソッドはテキスト全体をレンダリングするので、非常に長いテキストには使用しないでください。それを行う必要がある場合は、タイリングアプローチを検討する必要があります。見る WWDC 2013> 217-iOS 7でのスクロールビューの探索

this image

幸運を!

更新:(githubプロジェクトの画像)

enter image description here

21
sangonz

テキストを回転させる場合は、右から左へのレイアウトを使用して、ミラーリングの手順をスキップできるようにすることをお勧めします(逆に回転させるだけです)。

Label/textviewのtransformプロパティを設定するだけでよいはずです:

view.transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(CGFloat(-M_PI_2)), view.bounds.width, view.bounds.height)

ビューはその原点(左上)を中心に回転するため、回転後に移動する必要があります。

良いニュースは、ジェスチャーとタップがピクセルと同時に変換されるため、コントロールは期待どおりに機能し続けるということです。

3
Frank Schmitt