直近でやっていたプロジェクトでNSAttributedStringに関する知識が少なくて苦労したので忘れないようにメモしておきます。
NSAttributedStringに関してはすでに色んなブログやサイトで紹介されているのでご存知の方も多いかもしれませんが文字列を装飾してくれるクラスです。AndroidでいうところのImageSpanに相当します。
従来は単一のプロパティしか設定できず*1文字通りテキストを表示するラベルだったUILabelでしたが、iOS 6のころに複雑な表現ができるようにUILabelにNSAttributedStringを設定することができるようになりました。
当時のことはほとんど覚えていない……というよりもUILabelのサブクラスで自前描画*2することが多くてそれらの過去の遺産を継承していたので、僕の場合はNSAttributedStringクラスを本格的に使い出すようになったのはiOS 7.0からだと思います。
本記事ではNSAttributedStringを使って文字列を装飾する方法を紹介していきます。
まずはプロジェクトを適当に作っていただいて、ViewControllerにUILabelを貼り付けておいてください。名前はlabel
としましょう。UILabelはデフォルトの設定のままとしています。
UILabelにテキストを簡単に装飾して表示する
UILabelのプロパティにテキストカラーやフォントを指定します。UILabelに最も簡単にテキストを装飾して表示させる方法です。
self.label.text = "てすと" self.label.textColor = UIColor.whiteColor() self.label.textAlignment = NSTextAlignment.Center self.label.font = UIFont(name: "HiraKakuProN-W3", size: 10) ?? UIFont.systemFontOfSize(10)
下図のように表示されます。
iOSの各バージョンで使えるフォントに関しては「iOS 7 で使えるフォント名一覧 - Over&Out その後」で一覧を見ていただくと良いと思います。前職では「ヒラギノ角ゴシック」をよく使っていました。
NSAttributedStringを使って文字を装飾する(基本形)
UILabelのプロパティを指定せずにNSAttributedStringを使って、先ほどと同じように文字列を装飾してみましょう。
private func attribute1() -> NSAttributedString? { let font = UIFont(name: "HiraKakuProN-W3", size: 10) ?? UIFont.systemFontOfSize(10) let style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle style.alignment = NSTextAlignment.Center let attr = [ NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: font, NSParagraphStyleAttributeName: style, ] return NSAttributedString(string: "てすと", attributes: attr) }
先ほどのUILabelのプロパティを設定していた部分をコメントアウトしてしまって、UILabelのattributedTextプロパティにNSAttributedStringオブジェクトを設定します。
self.label.attributedText = attribute1()
下図のように表示されます。
NSAttributedStringの第二引数のattributes
の指定に使っているNSForegroundColorAttributeNameのようなキーは下記のようにたくさんあります。(虫食いになっているところは後で埋める)
キー | 説明 |
---|---|
NSFontAttributeName | フォント。デフォルトではHelvetica(Neue) 12pt が使われる |
NSParagraphStyleAttributeName | パラグラフ(段落)。デフォルトではdefaultParagraphStyleが使われる |
NSForegroundColorAttributeName | 文字色。デフォルトでは黒色が使われる |
NSBackgroundColorAttributeName | 背景色。デフォルトでは背景が存在しない(nil) |
NSLigatureAttributeName | |
NSKernAttributeName | 文字間。 |
NSStrikethroughStyleAttributeName | |
NSUnderlineStyleAttributeName | |
NSStrokeColorAttributeName | |
NSStrokeWidthAttributeName | |
NSShadowAttributeName | 影。デフォルトでは表示しない(nil) |
NSTextEffectAttributeName | テキストエフェクト。デフォルトでは表示しない(nil) |
NSAttachmentAttributeName | |
NSLinkAttributeName | |
NSBaselineOffsetAttributeName | |
NSUnderlineColorAttributeName | |
NSStrikethroughColorAttributeName | |
NSObliquenessAttributeName | |
NSExpansionAttributeName | |
NSWritingDirectionAttributeName | |
NSVerticalGlyphFormAttributeName |
UILabelに画像を表示する
NSAttributedStringを使ってUILabelに画像を表示させます。
private func attributeWithImage1() -> NSAttributedString? { let font = UIFont(name: "HiraKakuProN-W3", size: 10) ?? UIFont.systemFontOfSize(10) let style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle style.alignment = NSTextAlignment.Center let attr = [ NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: font, NSParagraphStyleAttributeName: style, ] var attrString = NSMutableAttributedString(string: "てすと", attributes: attr) // 画像はNSTextAttachmentで let attachment = NSTextAttachment() attachment.image = UIImage(named: "master") attachment.bounds = CGRect(x: 0, y: -2, width: 19, height: 19) attrString.appendAttributedString(NSAttributedString(attachment: attachment)) return attrString }
長いテキスト表示させた時に画像を残して文字列は省略する
とても長い文字列を表示させた時には下図のように表示されてしまいます。
lineBreakMode
にNSLineBreakMode.ByTruncatingTail
を設定するとお尻が省略されてしまうので、テキストを省略する必要のある場合にはNSLineBreakMode.ByTruncatingMiddle
を設定して、テキストの中央部分を省略します。
private func attributeWithImage2() -> NSAttributedString? { let font = UIFont(name: "HiraKakuProN-W3", size: 10) ?? UIFont.systemFontOfSize(10) let style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle style.alignment = NSTextAlignment.Center style.lineBreakMode = NSLineBreakMode.ByTruncatingMiddle let attr = [ NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: font, NSParagraphStyleAttributeName: style, ] // 長いテキスト var text = "" for i in 0..<20 { text += "てすと" } var attrString = NSMutableAttributedString(string: text, attributes: attr) // 画像はNSTextAttachmentで let attachment = NSTextAttachment() attachment.image = UIImage(named: "master") attachment.bounds = CGRect(x: 0, y: -2, width: 19, height: 19) attrString.appendAttributedString(NSAttributedString(attachment: attachment)) return attrString }
下図のように表示されます。
画像部分がハミ出しているのでテキストの高さと合わせたい
画像が大きかったのでテキストの高さに合わせます。
private func attributeWithImage3() -> NSAttributedString? { let font = UIFont(name: "HiraKakuProN-W3", size: 10) ?? UIFont.systemFontOfSize(10) let style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle style.alignment = NSTextAlignment.Center style.lineBreakMode = NSLineBreakMode.ByTruncatingMiddle let attr = [ NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: font, NSParagraphStyleAttributeName: style, ] var attrString = NSMutableAttributedString(string: "てすと", attributes: attr) // 画像はNSTextAttachmentで let attachment = NSTextAttachment() attachment.image = UIImage(named: "master") attachment.bounds = CGRect(x: 0, y: -1, width: font.leading, height: font.leading) attrString.appendAttributedString(NSAttributedString(attachment: attachment)) return attrString }
下図のように表示されます。
ちなみにこの画像のキャラはJenkinsくん(master)です。
関連記事
この他にもiOSアプリ開発で見つけたネタや悩んだ内容など紹介しています。Tipsをまとめておりますのでこちらのページをご参照ください。