質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.45%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

4164閲覧

Swift UITextViewにて単語の上にルビを付ける方法

NaohiroNomura

総合スコア10

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2017/01/15 04:27

趣味で小説サイトから小説をダウンロード、閲覧するアプリを作っています。

小説内で使われている単語などの上の行間に小さい文字でルビを付けたいと思っています。
iBook で購入した小説などは、単語の右側の行間(縦書き)にルビが挟んでありますが、そのようなに上手い具合に行間に収めたいです。

現在 UITextView にてテキストの表示を行なっているのですが、ルビを表示するのに何か上手い方法はないでしょうか?

初めは単語の上にラベルを置けばいいや、と思ったのですが、単語の途中で改行されている場合、ルビを二つに分割して出すことになるのであまりスマートじゃないやり方な気がしまして。。

上手い方法が思いつきません、、
UITextView ではなくても構いません。
上手い解決方法があれば教えてください。。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

以下のサイトはSwift2ではありますがやりたいことと同じだと思います、参考になるのではないでしょうか。

ルビを振る

Swift3で動かしてみました。

swift

1import UIKit 2 3extension String { 4 func find(pattern: String) -> NSTextCheckingResult? { 5 do { 6 let re = try NSRegularExpression(pattern: pattern, options: []) 7 return re.firstMatch( 8 in: self, 9 options: [], 10 range: NSMakeRange(0, self.utf16.count)) 11 } catch { 12 return nil 13 } 14 } 15 16 func replace(pattern: String, template: String) -> String { 17 do { 18 let re = try NSRegularExpression(pattern: pattern, options: []) 19 return re.stringByReplacingMatches( 20 in: self, 21 options: [], 22 range: NSMakeRange(0, self.utf16.count), 23 withTemplate: template) 24 } catch { 25 return self 26 } 27 } 28} 29 30class View: UIView { 31 32 override func draw(_ rect: CGRect) { 33 let text = [ 34 "「まさか、|後罪《クライム》の|触媒《カタリスト》を〈|讃来歌《オラトリオ》〉無しで?」", 35 "教師たちの狼狽した声が次々と上がる。", 36 "……なんでだろう。何を驚いているんだろう。", 37 "ただ普通に、この|触媒《カタリスト》を使って|名詠門《チャネル》を開かせただけなのに。", 38 "そう言えば、何を|詠《よ》ぼう。", 39 "自分の一番好きな花でいいかな。", 40 "どんな宝石より素敵な、わたしの大好きな緋色の花。", 41 "――『|Keinez《赤》』――", 42 "そして、少女の口ずさんだその後に――", 43 ] 44 .joined(separator: "\n") 45 46 let attributed = 47 text 48 .replace(pattern: "(|.+?《.+?》)", template: ",$1,") 49 .components(separatedBy: ",") 50 .map { x -> NSAttributedString in 51 if let pair = x.find(pattern: "|(.+?)《(.+?)》") { 52 let string = (x as NSString).substring(with: pair.rangeAt(1)) 53 let ruby = (x as NSString).substring(with: pair.rangeAt(2)) 54 55 var text: [Unmanaged<CFString>?] = [Unmanaged<CFString>.passRetained(ruby as CFString) as Unmanaged<CFString>, .none, .none, .none] 56 57 let annotation = CTRubyAnnotationCreate(.auto, .auto, 0.5, &text[0]!) 58 59 return NSAttributedString( 60 string: string, 61 attributes: [kCTRubyAnnotationAttributeName as String: annotation]) 62 } else { 63 return NSAttributedString(string: x, attributes: nil) 64 } 65 } 66 .reduce(NSMutableAttributedString()) { $0.append($1); return $0 } 67 68 var height = 28.0 69 let settings = [ 70 CTParagraphStyleSetting( 71 spec: .minimumLineHeight, 72 valueSize: Int(MemoryLayout.size(ofValue: height)), 73 value: &height) 74 ] 75 let style = CTParagraphStyleCreate(settings, Int(settings.count)) 76 77 attributed.addAttributes([ 78 NSFontAttributeName: UIFont(name: "HiraMinProN-W3", size: 14.0)!, 79 NSVerticalGlyphFormAttributeName: true, 80 kCTParagraphStyleAttributeName as String: style, 81 ], 82 range: NSMakeRange(0, attributed.length)) 83 84 let context = UIGraphicsGetCurrentContext() 85 86 context!.setFillColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 87 context!.addRect(rect) 88 context?.fillPath() 89 90 context!.rotate(by: CGFloat(M_PI_2)) 91 context!.translateBy(x: 30.0, y: 35.0) 92 context!.scaleBy(x: 1.0, y: -1.0) 93 94 let framesetter = CTFramesetterCreateWithAttributedString(attributed) 95 let path = CGPath(rect: CGRect(x: 0.0, y: 0.0, width: rect.height, height: rect.width), transform: nil) 96 let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, nil) 97 CTFrameDraw(frame, context!) 98 } 99} 100 101class ViewController: UIViewController { 102 override func loadView() { 103 super.loadView() 104 105 self.view = View() 106 } 107}

投稿2017/01/15 04:51

編集2017/01/15 05:48
_Kentarou

総合スコア8490

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NaohiroNomura

2017/01/15 05:23

素早い回答ありがとうございます。 早速試してみます!
NaohiroNomura

2017/01/15 07:06 編集

素早い回答だけでなく Swift3 への変換後コードの記述もしてくださるなど とても丁寧なご回答誠にありがとうございます。 大変助かりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.45%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問