Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Textの構造を理解する/Understanding the Structure of Text
Kakeru Nakabachi
November 29, 2021
Programming
1
490
Textの構造を理解する/Understanding the Structure of Text
Kakeru Nakabachi
November 29, 2021
Tweet
Share
More Decks by Kakeru Nakabachi
See All by Kakeru Nakabachi
チームで採用しているriverpodを使ったFlutterのアーキテクチャとriverpod v1.0.0
b4tchkn
6
2.5k
Other Decks in Programming
See All in Programming
設計の考え方とやり方
masuda220
PRO
56
31k
2022 - COSCUP - 打造高速 Ruby 專案開發流程
elct9620
0
100
ESM移行は無理だけどおれもSindreのライブラリが使いたい!
sosukesuzuki
2
550
Regular expressions basics/正規表現の基本
kishikawakatsumi
6
260
料理の注文メニューの3D化への挑戦
hideg
0
290
サーバーレスパターンから学ぶデータ分析基盤構築 / devio2022
kasacchiful
0
500
Better Angular Architectures: Architectures with Standalone Components @DWX2022
manfredsteyer
PRO
1
440
kintoneでランダム取得を作ってみた(imoniCamp 2022-07-27)
shokun1108
0
150
Atomic Design とテストの○○な話
takfjp
2
820
読みやすいコード クラスメソッド 2022 年度新卒研修
januswel
0
2.9k
FargateとAthenaで作る、機械学習システム
nayuts
0
190
Enzyme から React Native Testing Library に移行した経緯 / 2022-07-20
tamago3keran
1
160
Featured
See All Featured
Documentation Writing (for coders)
carmenintech
48
2.6k
Design by the Numbers
sachag
271
17k
Visualization
eitanlees
125
12k
Building a Scalable Design System with Sketch
lauravandoore
448
30k
How To Stay Up To Date on Web Technology
chriscoyier
780
250k
The Web Native Designer (August 2011)
paulrobertlloyd
75
2k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
15
3.8k
Rebuilding a faster, lazier Slack
samanthasiow
62
7.3k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
21
1.4k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
316
19k
Gamification - CAS2011
davidbonilla
75
3.9k
Faster Mobile Websites
deanohume
294
28k
Transcript
Textの構造を理解する Flutter Kaigi 2021 November 29-30, 2021
Kakeru Nakabachi - batch CyberAgent, Inc 株式会社WinTicketでモバイルアプリをFlutterでリ プレイス中 About me
2
本セッションのゴール Textの構造を理解して実装できるようになる💪💪 3
アジェンダ • Text • Textの構造 • AndroidとiOSでTextを描画したときの問題について • チームで対応した問題の対処法 •
まとめ 4
Text 5
Text 文字を表示するためのWidget • プロパティたち ◦ maxLines ◦ overflow ◦ strutStyle
◦ style ◦ textAlign ◦ textHeightBehavior ◦ ... https://api.flutter.dev/flutter/widgets/Text-class.html 6
Text 文字を表示するためのWidget • プロパティたち ◦ maxLines ◦ overflow ◦ strutStyle
◦ style ◦ textAlign ◦ textHeightBehavior ◦ ... https://api.flutter.dev/flutter/widgets/Text-class.html debugLabel fontFamily fontFamilyFallback fontSize fontStyle fontWeight forceStrutheight hashCode height leading leadingDistribution 7 TextStyleのプロパティ
Text 8 https://api.flutter.dev/flutter/painting/TextStyle-class.html
Text 9 https://api.flutter.dev/flutter/painting/TextStyle-class.html
Text 文字を表示するためのWidget • maxLines • overflow • strutStyle • style
• textAlign • textHeightBehavior • ... https://api.flutter.dev/flutter/widgets/Text-class.html 10
Text 文字を表示するためのWidget • maxLines • overflow • strutStyle • style
• textAlign • textHeightBehavior • ... https://api.flutter.dev/flutter/widgets/Text-class.html 11
Text 文字を表示するためのWidget • maxLines • overflow • strutStyle • style
• textAlign • textHeightBehavior • ... https://api.flutter.dev/flutter/widgets/Text-class.html 12
Textの構造 13
Textの構造 このようなTextを表示した場合、どのような構造でTextが構築されて表示されて いるかをみていく Flutterのvisual debuggingツールを有効化 https://flutter.dev/docs/testing/debugging#visual-debugging https://docs.flutter.dev/development/tools/devtools/inspector 14
Textの構造 実行結果 Android https://api.flutter.dev/flutter/painting/TextStyle-cl ass.html Textが確保している領域 15
Textの構造 実行結果 Android https://api.flutter.dev/flutter/painting/TextStyle-cl ass.html Textのbaseline 16
それぞれの線の意味 baseline ascent: baselineから上部までの高さ descent: baselineから下部までの高さ leading: ある行の下端から次の行の上端までの高さ、TextStyle.height * TextStyle.fontSize
- TextStyle.fontSize これらを意識してTextをつくっていく。今回は以下の3つにフォーカスする height、leadingDistribution、textHeightBehavior Textの構造 AaBbGgJj 17
Textの構造 • height 行の高さをフォントサイズの倍数で調整で きる nullと1.0は別の意味 18 https://api.flutter.dev/flutter/painting/TextStyle-class.html
Textの構造 • leadingDistribution leadingを上下にどのように配置するかを決める。 asent descent Top leading Bottom leading
19
Textの構造 • leadingDistribution TextLeadingDistribution.proportionalと.evenがある leadingを上下にどのように配置するかを決める。nullの場合は TextLeadingDistribution.proportionalと同じ挙動 20
Textの構造 • leadingDistribution leadingを上下にどのように配置するかを決める。 TextLeadingDistribution.evenにした場合はascentとdescentから上下に等 しくleadingが設定される 21
Textの構造 • textHeightBehavior applyHeightToFirstAscentとapplyHeightToLastDescentのbool値を設定す ることでTextの上下のleadingを除くことができる デフォルトはtrueでleadingあり falseを設定してleadingを除いた場合、textHeightBehaviorは効かなくなる 22
Textの構造 • heightとleadingDistributionとtextHeightBehavior Configuration 1 fontSizeとheight以外はすべてデフォル ト設定 leadingDistributionは TextLeadingDistribution.proportional 23
Textの構造 • heightとleadingDistributionとtextHeightBehavior Configuration 2 Configuration 1に TextHeightBehavior.applyHeightToFir stAscentをfalseに設定 24
Textの構造 • heightとleadingDistributionとtextHeightBehavior Configuration 3 leadingDistributionを TextLeadingDistribution.evenに設定 25
Textの構造 • heightとleadingDistributionとtextHeightBehavior Configuration 4 Configuration 3の設定に TextHeightBehavior.applyHeightToLa stDescentにfalseを追加で設定したとき 26
Textの構造 • 複数行の場合 27
Textの構造 • 複数行の場合 height: 2.5を追加 28
Textの構造 • 複数行の場合 TextHeightBehavior.applyHeightToFirstAscent: falseを追加 29
Textの構造 • 複数行の場合 TextHeightBehavior.applyHeightToLastDescent: falseを追加 30
Textの構造 • 複数行の場合 leadingDistributionにTextLeadingDistribution.proportionalの設定 31
Textの構造 • 複数行の場合 leadingDistributionにTextLeadingDistribution.evenの設定 32
Textの構造 • 複数行の場合 TextStyleのleadingDistributionとTextHeightBehaviorの leadingDistribution TextStyle側が優先されて使われる 33
Textの構造 • 複数行の場合 TextStyleのleadingDistributionとTextHeightBehaviorの leadingDistribution TextStyle側が優先されて使われる 34
AndroidとiOSでTextを描画したときの 問題について 35
問題1:OSごとにTextのサイズが違う • 実はAndroidとiOSでは同じフォントサイズなどstyleの設定でもTextの高さ が異なる ➢ 高さ固定のWidgetの中にTextなど配置した場合に、片方のOSでは収ま るけど、もう一方では収まらなかったり、OS間で異なったデザインにな る 両OSのデザインがある場合は大丈夫 弊チームではiOSのデザインしかなくどのように対応するか考える必要があった
36
問題1:OSごとにTextのサイズが違う 実はiOSとAndroidでは同じフォントサイズなどの設定でもTextの高さが異なる Android 37
問題1:OSごとにTextのサイズが違う 実はiOSとAndroidでは同じフォントサイズなどの設定でもTextの高さが異なる iOS 38
問題1:OSごとにTextのサイズが違う なぜ起こる? OSによってleadingの高さが違う、、? →TextHeightBehaviorを設定して上下のleadingをなくしたらどうなるか AaBbGgJj 39
問題1:OSごとにTextのサイズが違う TextHeightBehaviorを設定してみる Android 40
問題1:OSごとにTextのサイズが違う TextHeightBehaviorを設定してみる iOS 41
問題1:OSごとにTextのサイズが違う AndroidとiOSでTextHeightBehaviorの設定の挙動が違いそう?バグ、、? Android iOS 42
問題1:OSごとにTextのサイズが違う 結論:fontFamilyを指定しなかった場合、OSごとに読み込まれるフォントが異 なり、ascentとdescentが異なるため Android Pixel 4a 和文フォント:Noto Sans Japanese? 欧文フォント:Roboto
iOS iPhone 12 Pro 和文フォント:ヒラギノ角ゴシック 欧文フォント:San Francisco Pro 43
問題1:OSごとにTextのサイズが違う TextStyle.backgroundColorを設定して、Textの中でフォントが確保している領域 を見てみる。和文フォントで大きく確保する領域に違いがある Android iOS 44
問題1:OSごとにTextのサイズが違う TextStyle.backgroundColorを設定して、Textの中でフォントが確保している領域 を見てみる。和文フォントで大きく確保する領域に違いがある Android iOS Androidのフォントが確保している領域が iOSより広い 45
問題2:Androidだと文字が下寄りに見える https://github.com/flutter/flutter/issues/79931 46
問題2:Androidだと文字が下寄りに見える Android iOS 24.0 32.0 fontSize 47
問題2:Androidだと文字が下寄りに見える Androidの方がフォントがデフォルトで確保している ascentとdescentが大きく、ascentの方が大きいので 下寄りに見える Android iOS 48
問題2:Androidだと文字が下寄りに見える Androidの方がフォントがデフォルトで確保しているascentと descentが大きく、ascentの方が大きいので下寄りに 見える Android iOS 49
チームで対応した問題の対処法 50
チームで対応した問題の対処法 ▪ 一般的な対処法と思われるもの • AndroidとiOSで共通のascentとdescentが小さいフォントを使う • AndroidだけiOSのシステムフォントのようなascentとdescentが小さい フォントを使う 51
チームで対応した問題の対処法 ▪ 一般的な対処法と思われるもの • AndroidとiOSで共通のascentとdescentが小さいフォントを使う • AndroidだけiOSのシステムフォントのようなascentとdescentが小さい フォントを使う ➢ 弊チームでの対応はこれ
52
チームで対応した問題の対処法 ▪ AndroidでiOSのシステムフォントのようなascentとdescentが小さいフォン トを使うためには Androidで角ゴシックを使えば両プラットフォームで全く同じTextにすることが できるが、、、 ➢ Androidユーザは普段と違うフォントを目にすることになって違和感か もしれない ➢
ライセンス問題( https://developer.apple.com/forums/thread/89094 ) 53
チームで対応した問題の対処法 ▪ Android用にascentとdescentが小さいフォントを用意する必要がある ➢ NotoSans CJKを使用 CJK = Chinese Japanese
Korean 今はJapaneseのみが入ったファイルサイズの小さいNotoSansJapaneseがあ る https://fonts.google.com/noto/specimen/Noto+Sans+JP 54
チームで対応した問題の対処法 ▪ Android用にascentとdescentが小さいフォントを用意する必要がある NotoSans CJKのままでは、中国語や韓国語など使わないフォントも多いので、サ ブセット化してフォントファイルサイズを削減 .otf → .woff →
.ttf → サブセット化(JIS第1水準+JIS第2水準+その他) NotoSans CJK RegularとNotoSans CJK Boldを用意 サブセット化前 サブセット化後 34MB 3MB 55
チームで対応した問題の対処法 ▪ Android用にascentとdescentが小さいフォントを用意する必要がある コンバートする段階でascentとdescentが除かれたフォントができあがることを 利用してiOSのフォントのような扱いをしている https://github.com/minoryorg/Noto-Sans-CJK-JP ライセンス的には商用利用可、改変可 https://fonts.google.com/noto/use#bundle-noto-fonts-with-your-native-app https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL 56
チームで対応した問題の対処法 ▪ Android用にascentとdescentが小さいフォントを用意する必要がある フォントの指定方法 なにも指定がない場合、OSのデフォルトのシステムフォントが使われる 57 ← 最初に読み込もうとするフォントを指定 ← fontFamilyで対応できなかった文字を描画す
るためのフォントを指定
チームで対応した問題の対処法 ▪ Android用にascentとdescentが小さいフォントを用意する必要がある フォントの指定方法 用意したフォントは日本語表示用に、英語はシステムフォントでデフォルトで選 択されるRobotoを使いたい fontFamilyに何も指定しない場合→Robotoが使われる 日本語を表示しようとしたとき、Robotoだけでは対応できずfontFamilyFallback に設定されているフォントを読み込もうとする なので、今回は用意したフォントをfontFamilyFallbackに設定
58
チームで対応した問題の対処法 ▪ ボタンなどの垂直方向の中央に文字が表示されるようにleadingの調整 ascentとdescentが小さいフォントを使うことにより、 デフォルトのleadingが効 くようになり、文字が厳密にはまだ中心に配置されていない TextStyle.leadingDistributionにTextLeadingDistribution.evenを設定して、上 下に等しくleadingを配置して文字が垂直方向に中心に配置されるようにする 59 フォント変更前
フォント変更後
まとめ • Textは様々な要素で構成されている • AndroidとiOSではフォントを指定しない場合、読み込むシステムフォントが それぞれ違うため、全く同じ見た目のTextを描画しない ◦ 高さが違う ◦ 文字が下よりに見える
• 対応方法の1つにAndroidのときはデフォルトでasecntとdescentが大きいシ ステムフォントが使われるため、それらが小さいフォントを指定してiOSの 挙動に近づける • TextStyle.leadingDistributionにTextLeadingDistribution.evenを設定して 上下のleadingを均等に配分して文字を中央にする 60
参考 • https://flutter.dev/docs/testing/debugging#visual-debugging • https://flutter.dev/docs/development/tools/devtools/inspector • https://stackoverflow.com/questions/56799068/what-is-the-strutstyl e-in-the-flutter-text-widget • https://api.flutter.dev/flutter/painting/TextStyle-class.html
• https://github.com/flutter/flutter/issues/79931 • https://fonts.google.com/noto/use#bundle-noto-fonts-with-your-nativ e-app • https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL • https://github.com/minoryorg/Noto-Sans-CJK-JP 61
Thank you 62