Original Link
by Rob Huebner
translated Korean by pilgwon
他に注目するほどのことがない水曜の朝に、Slackのアラートに沈黙は破られた。それはデザイン担当だった。彼はうちのフォントにちょっとした修正可否を訪ねてきた。"はい、そしてうちのすべてのトラッキング(tracking)もちょっとずつ修正する必要があるようです"
基本的な属性
このリクエストがなぜでっかい仕事なのか理解するため、iOSでテキストを見せてくれるに一番基本的な方法であるUILabel
を利用してみましょう。
もしあなたが作業するところにUIKit
を利用するのであれば、UILabel
に関するよく知っていると思います。これは些細なUIをカスタマイズ可能な属性であるfont
、textColor
、そしてtextAlignment
の属性を持っています。しかしその後貴方は壁にぶつかり始めることになると思います。ある格好いい作業をするためには普通テキストとそれにふさわしい適切な属性を持っているNSAttributedString
が必要になり、label
のattributedText
属性を利用します。
それは良さげに見えますがこのやり方を拡張するなり、他の方法を考えて見ると:
- attributedStringを作るのは結構ごつくて不必要に見えます。
- labelのテキストが動的であれば、スタイルが変わっていないとしても貴方はすべての
attributedString
をテキストに変更するたびに新たに実装しないといけません。 - 文字列のスタイルを標準化したり、デフォルト値を元で構築する方法は存在しません。
トラッキングあるいはカーニング(アップルはこう呼んでます)はattributedString
で飲み使えるパラメーターの一つです。なので、もしフォントのカーニングを全体的に調整するためにはtextの代わりにattributedText
を全体的に使う必要があります。ただ、これは結構コード複雑度を招く恐れがあります。
ではもっと良さげなフォントシステムを作ってみましょ。
テキストスタイル
attributed stringを必要なすべての箇所に手動で追加する作業は本当にやりたくありませんでした。
静的テキストスタイルはテキスト自体とは独立的に宣言するのがいいと思います。そうすると、labelのライフサイクルを早い段階でスタイルが設定でき、後からは考えなくてもよくなります。
そのため、iOSの宣言的なテキストスタイリングライブラリーであるStyledText
を実装しました。StyledText
は二つのコンセプトを説明します。: TextStyle
, 特定テキストスタイルパラメーターセットを表すタイプ; そしてスタイルを受け入れてテキスト内容を描く時に利用するUIViewのサブクラスであるStyled. ただTextSTyleを上に実装して、StyledLabel
に送れば終わりです:
class ViewController: UIViewController {
private let styledLabel: StyledLabel = {
let label = StyledLabel(frame: .zero)
label.textStyle = TextStyle(font: .systemFont(ofSize: 14),
color: .blue,
lineSpacing: 4.0,
kern: 1.5)
return label
}()
func updateLabel() {
styledLabel.text = "This is a simple string"
}
}
実用性あるデフォルト値
前に出ていたのは素晴らしいですが、まだ結果的にすべての問題を解決はできておりません。どうやってアプリのカーニングの調整をすればよろしいでしょうか。その答えはTextStyle
にあります。ここではTextStyleDefaultsGenerator
と名付けます。この中で一つ設定を行えばスタイルは指定されていないまま初期化されるたびにカーニングのデフォルト値を設定できます。
extension TextStyle: TextStyleDefaultsGenerator {
private static let defaultCeraKern: CGFloat = -0.2
private static let defaultChronicleKern: CGFloat = -0.2
static public func defaultKern(for font: UIFont) -> CGFloat? {
if font.fontName.contains("Cera") {
return defaultCeraKern
} else if font.fontName.contains("Chronicle") {
return defaultChronicleKern
}
return nil
}
}
問題解決. 😎
Blue Apron iOS アプリに TextStyleを適用してからフォントはどこからでも詳細の内容まで設定が可能になり、オーバーヘッドの負担も少なくなります。そしてStyledText
をオープンソースライブラリーでiOSコミュニティに公開することになりました。続けて修正されれモバイルプラットフォームに役に立つ強いタイプグラプィツールになれば嬉しいと思います。
ボーナス: 自然な接近が勝ちます!
我々はすべてのテキストスタイリングを中央集中式にて実装していて対応可能な機能は多いと思います。例えば、ユーザーがそれらのシステムフォントサイズを変更可能にするアップルのツールである動的フォントサイズに対応が可能になります。StyledText
のすべての含まれているのはすべてのTextStyle
に動的にフォントサイズを指定できる機能です。:
貴方のテキストを作り上げて見てください
GitHubにあるREADMEをご確認ください! Contributeも積極的に受け入れます。
[ * ] タイプグラプィは実際、 “カーニング(kerning)”をふた文字の間の空間で定義します。. 例えば、 ‘A’と ‘V’の模様は重ねることができるため多くのフォントで近くついてします。. “トラッキング(Tracking)”はもっと大きい任意の文字列に関して文字間隔の調整を見せてくれます。. ただアップルは文字列属性の NSKernAttributeName
で前の2つの概念を提供してくれるのえStyledText
も同じであります。