Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Textの構造を理解する/Understanding the Structure of Text
Search
Kakeru Nakabachi
November 29, 2021
Programming
2.8k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Textの構造を理解する/Understanding the Structure of Text
Kakeru Nakabachi
November 29, 2021
More Decks by Kakeru Nakabachi
See All by Kakeru Nakabachi
Flutterアプリで可用性を向上させたFeatureFlagの運用戦略とその方法
b4tchkn
0
2k
Inside Flutter Text
b4tchkn
1
310
Flutterアプリのセキュリティ対策を考えてみる
b4tchkn
6
8.3k
チームで採用しているriverpodを使ったFlutterのアーキテクチャとriverpod v1.0.0
b4tchkn
6
5k
Other Decks in Programming
See All in Programming
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
170
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
150
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
700
週末にAI-DLCを本気で回したら$1,600溶けた
hbashimizu
0
130
What We Talk About When We Talk About XP
m_seki
2
450
AWS DevOps Agentで インシデント対応をAIに任せたい
honmarkhunt
7
2.7k
Intent as Code
shoppingjaws
4
700
Foundry Localでエージェント開発
seosoft
0
160
スマート反転とウェブアクセシビリティ
camiha
0
180
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
5.7k
自分的「カンファレンスの楽しみ方」
syumai
0
200
Gmail/Google DriveをトリガーにAIエージェントを動かそう! / Run AI agents with Gmail/Google Drive as triggers!
har1101
3
490
Featured
See All Featured
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
410
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3k
Test your architecture with Archunit
thirion
2
2.4k
Google's AI Overviews - The New Search
badams
0
1.6k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
510
My Coaching Mixtape
mlcsv
0
310
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Six Lessons from altMBA
skipperchong
29
4.5k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
490
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
590
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
270
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