UITextViewでハッシュタグとメンションを色を変えて表示とタップ検知をする
UITextViewで複数のハイライトを表現したい
最近の実装でSNSなどの普及でか#swift
などのハッシュタグに加えて@rinov
など個別にハイライトして、タップしたときの挙動も柔軟に指定したい時がありました。
基本的には標準のNS***AttributeName
などで該当の単語ごとにNSRange
を求めて属性を追加するのですが、この実装方法はかなり良くないと感じました。
Attribute Stringの問題点
UITextView
を用いて文字を装飾したい場合にはAttributedString
で属性と値を指定することで実現します。
例: UITextViewのテキストを赤くする
textView.text = "Hello World" let attributedText = textView.mutableCopy() as? NSMutableAttributedString attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSMakeRange(0, 5)) textView.attributedText = attributedText
問題点
- NS***AttributeNameというグローバルな値が属性のキーになっているため一覧性がない
UITextView
のaddAttribute
は値がAny型となっているため、例えばテキストカラーを設定するときにUIColorが設定されることが自明でありながら.red
などの省略が行えない。また、どんな値でも引数に渡せてしまい安全でない。- NSMutable~, NSRange, NS***AttributeNameなどObjective-Cの遺産を多く使用している。
- ハイライトする単語の
NSRange
を毎回算出するのが面倒である
上記の例では色を付けるだけでしたが多くの場合特定のキーワードを個別にハイライトしたりタップ時の挙動を柔軟に変更したいです。
UITextView
のプロパティとしてlinkTextAttributes
というものがありますが、これはリンク属性の付いたテキストの見た目を一括で装飾の指定を行うことができますが、例えば、ハッシュタグは青色、メンションは赤色など個別に対応した属性の指定を行うことはできません。
// 単語ごとに個別の指定は行えない textView.linkTextAttributes = [NSForegroundColorAttributeName: UIColor.red]
こういったObjective-CとSwiftの間でコーディングしている感があり、今後Swiftのバージョンアップした時に既存のコードを全て実装しなおすリスクも考えるとなかなか気が進みません。
そこで最近のリッチなテキストを柔軟にカスタマイズしたいと思い、UITextView
で実装したものをライブラリ化しました。
RegeributedTextView
https://github.com/rinov/RegeributedTextView
使い方はREADME.md
またはhttp://qiita.com/rinov/items/da450d0ba9dffaaf8967にまとめました。
調べた限りでもTTTAttributedLabel
など有名なライブラリ(UILabel専用)がありますが、Swift製で正規表現 + 独自のTextAttributeプロパティを追加しているライブラリはありませんでした。複数単語のハイライトやタップした単語ごとに任意の処理をしたいなどがありましたら一度使用してみていただけると嬉しいです。
またGithubでIssueやPR等いただけるとさらに嬉しいです。