ParagraphStyle — 主要概念、プロパティ、適用方法

著者: IT Sectr 公開日: 2026-07-25 読了時間: 10 分

ParagraphStyleは、テキスト段落の視覚的な外観を定義する書式設定パラメータのセットです。モバイル開発において、ParagraphStyleには配置(left、center、right、justified)、行間隔、最初の行のインデント、段落間の間隔、テキストの方向が含まれます。Material Design Typography Guidelines(2025)によると、アプリケーションのすべての画面でParagraphStyleを一貫して使用することで、統一されたタイポグラフィックリズムが確保され、セクション間の切り替え時の視覚的なノイズが軽減されます。

重要なポイント

  • ParagraphStyle — 段落書式設定オブジェクト:配置、インデント、間隔。
  • プラットフォーム — iOS:NSMutableParagraphStyle、Android:ParagraphStyle(Compose)/ Layout(View)、Flutter:TextStyle。
  • 配置 — 本文テキストはleft、見出しはcenter、書籍形式はjustified。
  • インデント — firstLineHeadIndent(最初の行のインデント)、paragraphSpacing(段落間の間隔)。
  • ローカライゼーション — ParagraphStyleは異なる言語のテキスト方向(LTR/RTL)を考慮します。

タイポグラフィにおけるParagraphStyleとは

ParagraphStyle(段落スタイル)は、1つ以上のテキスト段落に適用可能な書式設定ルールの集合です。個々の文字レベルで機能する文字スタイル(bold、italic、font-size)とは異なり、ParagraphStyleはマクロプロパティを管理します:コンテナ内のテキスト配置、行間および段落間の間隔、書記方向、ハイフネーションルール。

歴史的に、ParagraphStyleの概念はデスクトップパブリッシングシステム(QuarkXPress、PageMaker、InDesign)から来ており、各段落に独自のパラメータセットがありました。モバイル開発では、このアプローチはソフトウェアAPIに変換されました:iOSのNSMutableParagraphStyle、AndroidのParagraphStyleおよびLineBreakStyleクラス、FlutterのtextAlignやtextHeightBehaviorなどのパラメータ。これらはすべて1つの目的を果たします — 段落書式の管理を、特定のテキストエンジンに縛られることなくコードを通じて行います。

Bringhurst — The Elements of Typographic Style(2024)によると、適切なParagraphStyleの設定はインターフェースのタイポグラフィ文化の基礎です。書体とフォントサイズがテキストの「声」を定義するなら、段落スタイルはその「呼吸」を定義します:リズム、ポーズ、アクセント。スペースが限られているモバイルインターフェースでは、適切なParagraphStyleによって、可読性を損なうことなくより多くの情報を収めることができます。

ParagraphStyleの主要プロパティ

ParagraphStyleには、それぞれが書式設定の特定の側面を担当するいくつかのプロパティグループが含まれます。モバイルAPIで利用可能な主要パラメータを見てみましょう。配置は、テキストの水平位置を決定する主要なパラメータです。iOSではNSTextAlignment、AndroidではLayout.Alignment、FlutterではTextAlignが利用可能です。

プロパティiOS(NSMutableParagraphStyle)Android(Compose)Flutter(TextStyle)
配置alignmenttextAligntextAlign
左インデントheadIndenttextIndent(Composeの場合)
右インデントtailIndent
最初の行のインデントfirstLineHeadIndenttextIndent(firstLine)
段落間の間隔paragraphSpacingparagraphStyle(lineHeight)
段落前の間隔paragraphSpacingBefore
テキストの方向baseWritingDirectionTextDirection(Compose)textDirection
改行モードlineBreakModeoverflow(TextStyle)overflow(TextStyle)

すべてのプロパティがすべてのプラットフォームで同じ程度に利用できるわけではないことを理解することが重要です。たとえば、最初の行のインデント(firstLineHeadIndent)は、NSMutableParagraphStyleを介してiOSでのみ完全にサポートされています。Androidでは、この目的のためにLeadingMarginSpanを使用したSpannableStringが使用され、FlutterではカスタムTextSpanとパディングを使用したRichTextが使用されます。クロスプラットフォーム開発(Flutter、React Native)では、一部のParagraphStyleプロパティをコンテナやSpacerを介してエミュレートする必要があります。

iOSのParagraphStyle:NSMutableParagraphStyle

iOSでは、段落スタイルを扱うための主要なツールはNSMutableParagraphStyleクラスです — NSParagraphStyleのサブクラスです。これは段落書式を管理するための完全なプロパティセットを提供し、NSAttributedStringを介して適用されます。NSMutableParagraphStyleは、UILabelやUITextViewだけでなく、CTParagraphStyleを介したCore Textでも使用されます。

swift
// iOS:完全なParagraphStyle設定
let paragraphStyle = NSMutableParagraphStyle()

// 配置
paragraphStyle.alignment = .justified     // 両端揃え

// インデント
paragraphStyle.headIndent = 16          // 左インデント
paragraphStyle.tailIndent = -16         // 右インデント(負の値)
paragraphStyle.firstLineHeadIndent = 32 // 最初の行のインデント

// 段落間隔
paragraphStyle.paragraphSpacing = 12    // 段落の後
paragraphStyle.paragraphSpacingBefore = 8 // 段落の前

// 行の高さ
paragraphStyle.minimumLineHeight = 24
paragraphStyle.maximumLineHeight = 24

let attributes: [NSAttributedString.Key: Any] = [
    .font: UIFont.systemFont(ofSize: 16),
    .paragraphStyle: paragraphStyle
]

let label = UILabel()
label.attributedText = NSAttributedString(
    string: "This paragraph has a custom ParagraphStyle.\n\nSecond paragraph with 12 pt spacing.",
    attributes: attributes
)

SwiftUIには、NSMutableParagraphStyleに直接相当するものはありません — 代わりに、修飾子の組み合わせが使用されます:配置には.multilineTextAlignment()、行間隔には.lineSpacing()。SwiftUIで最初の行のインデントと段落間隔を設定するには、Text + padding、またはNSParagraphStyleを属性を介してサポートするAttributedString(iOS 15+以降で利用可能)を使用する必要があります。

swift
// SwiftUI:ParagraphStyleを使用したAttributedString(iOS 15+)
var attributed: AttributedString = """
This is the first paragraph with indent.

This is the second paragraph with 12 pt spacing.
"""

let ps = NSMutableParagraphStyle()
ps.paragraphSpacing = 12
ps.firstLineHeadIndent = 20

let container = AttributeContainer()
    .paragraphStyle(ps)

attributed.mergeAttributes(container)

Text(attributed)
    .font(.body)

Apple — Text Programming Guide(2025)によると、NSMutableParagraphStyleは最大14の異なる書式設定パラメータをサポートしています。tailIndentはコンテナの幅に対して負の値で設定され、headIndentは正の値であることを覚えておくことが重要です。このわかりにくい動作は、初心者のiOS開発者にしばしばエラーを引き起こします。

AndroidのParagraphStyle:ViewシステムとCompose

Androidでは、ParagraphStyleへのアプローチはViewシステムとJetpack Composeで異なります。従来のViewシステムでは、段落パラメータはTextViewのXML属性(android:textAlignment、android:lineSpacingExtra)またはandroid.text.styleパッケージのParagraphStyleインターフェースの実装を使用したSpannableStringを介して設定されます。

kotlin
// Android Viewシステム:SpannableStringによるParagraphStyle
val text = "First paragraph with settings.\n\nSecond paragraph."
val spannable = SpannableString(text)

// 両端揃え
spannable.setSpan(
    AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
    0, text.length,
    Spannable.SPAN_PARAGRAPH
)

// LeadingMarginSpanによる最初の行のインデント
spannable.setSpan(
    LeadingMarginSpan.Standard(0, 20),
    0, text.indexOf('\n'),
    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)

textView.text = spannable

Jetpack Composeでは、ParagraphStyleはTextStyleパラメータを介して管理されます。配置にはtextAlign、行間隔にはlineHeight(spまたはem)、最初の行のインデントにはtextIndentが使用されます。Composeはまた、改行の細かい制御のためのLineBreak(Simple、Heading、Paragraph)をサポートしており、これは多言語テキストに特に役立ちます。

kotlin
// Jetpack Compose:TextStyleによるParagraphStyle
Text(
    text = "カスタムスタイルの最初の段落。

インデント付きの2番目の段落。",
    style = TextStyle(
        textAlign = TextAlign.Justify,
        lineHeight = 24.sp,
        textIndent = TextIndent(firstLine = 16.sp),
        lineBreak = LineBreak.Paragraph
    )
)

Android Developers — Compose ParagraphStyle(2025)によると、ComposeでTextIndentを使用する場合、最初の行のインデントはテキストとともに拡大縮小する必要があるため、firstLineをsp(dpではなく)で設定することが重要です。インデントがdpで設定されている場合、フォントサイズが大きくなると最初の行のインデントが視覚的に小さくなり、タイポグラフィの比率が崩れます。

FlutterのParagraphStyle:TextHeightBehaviorとStrutStyle

Flutterでは、ParagraphStyleのパラダイムは専用クラスに分離されていません — 代わりに、TextStyleパラメータと追加クラスの組み合わせが使用されます。配置はTextAlign、行間隔はheight(単位なし)、TextHeightBehaviorは最初と最後の行の表示インデントを制御します。

dart
// Flutter:TextパラメータによるParagraphStyle
Text(
    'Flutterでスタイル設定された段落。

インデント付きの2番目の段落。',
    style: TextStyle(
        fontSize: 16,
        height: 1.5,
        leadingDistribution: TextLeadingDistribution.proportional,
    ),
    textAlign: TextAlign.justify,
    textHeightBehavior: TextHeightBehavior(
        applyHeightToFirstAscent: true,
        applyHeightToLastDescent: true,
    ),
)

より複雑なシナリオでは、FlutterはカスタムTextSpanおよびWidgetSpanを使用したRichTextの使用を提供します。これにより、統一された書式設定ルールを維持しながら、単一の段落内でテキストとインラインウィジェット(アイコン、画像)を組み合わせることができます。ただし、このアプローチでは改行の手動制御が必要であり、自動ハイフネーションをサポートしていません。

dart
// Flutter:カスタム段落書式を使用したRichText
RichText(
    text: TextSpan(
        style: TextStyle(fontSize: 16, height: 1.5),
        children: [
            TextSpan(text: 'First paragraph with icon '),
            WidgetSpan(
                child: Icon(Icons.star, size: 16),
                alignment: PlaceholderAlignment.middle,
            ),
            TextSpan(text: '\n\nSecond paragraph after spacing.'),
        ],
    ),
)

Flutter Documentation — Text Widget(2025)によると、TextHeightBehaviorはFlutterでParagraphStyleを正しく表示するための重要なパラメータです。applyHeightToFirstAscentがfalseに設定されている場合、最初の行の上部インデントが無視され、テキストがコンテナの上端に「くっつきます」。これは見出しには便利ですが、本文テキストには望ましくありません。

ParagraphStyleとローカライゼーション:LTR/RTLと地域固有の特徴

ParagraphStyleは、各ロケールの書記方向を考慮する必要があります。アラビア語、ヘブライ語、ウルドゥー語(右から左への書記、RTL)をサポートするモバイルアプリでは、インデントと配置がミラーリングされる必要があります。iOSはbaseWritingDirection = .naturalによる自動切り替えをサポートし、AndroidはTextDirection、FlutterはtextDirectionをサポートしています。

RTLロケールの配置設定には特に注意が必要です。LTRモードでheadIndentが左インデントを設定する場合、RTLでは自動的に右インデントになります。ただし、配置が明示的に指定されている場合(NSTextAlignment.naturalではなくNSTextAlignment.left)、すべての実装がこの遷移を正しく処理するわけではありません。Google Internationalization Guide(2025)によると、多言語アプリでは常に自然配置を使用し、両方のレイアウトでインデントを確認してください。

kotlin
// Android:ParagraphStyleのRTLサポート
val textView = TextView(context)

// 自動RTLサポートを有効にする
textView.textDirection = View.TEXT_DIRECTION_LOCALE
textView.textAlignment = View.TEXT_ALIGNMENT_TEXT_START

// RTLサポート付きSpannable
val spannable = SpannableString(arabicText)
spannable.setSpan(
    AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
    0, arabicText.length,
    Spannable.SPAN_PARAGRAPH
)

地域固有の特徴には、最初の行のインデントに関する異なるルールも含まれます。ヨーロッパのタイポグラフィでは、最初の行のインデント(firstLineHeadIndent)は段落区切りの標準です。日本と中国のタイポグラフィでも最初の行のインデントが使用されますが、そのサイズは異なる場合があります(ヨーロッパの伝統では1.5 emに対して通常1 em)。アラビア語のタイポグラフィでは、最初の行のインデントはまれで、段落はより頻繁に垂直方向の間隔で区切られます。

ParagraphStyleを使用する際のよくある間違い

最も一般的な間違いは、個々の段落の異なる書式を考慮せずに、テキストフィールドのグローバル属性のみを介してParagraphStyleを使用することです。 で区切られた複数の段落があるUILabelまたはTextViewでは、各段落に異なるスタイルの属性付きテキストを使用しない限り、ParagraphStyleはテキスト全体に均一に適用されます。

  • paragraphSpacingBeforeを無視する — 多くの開発者はparagraphSpacingを設定しますが、paragraphSpacingBeforeを忘れています。ブロックの最初の段落では、paragraphSpacingBeforeは追加のコンテナを作成せずに上部マージンを設定できます。これは見出し付きのリストで特に便利です。
  • 自然配置の代わりにハードコードされた配置(left/right) — アプリがRTLロケールをサポートしている場合、naturalの代わりにNSTextAlignment.leftやTextAlign.Startを使用すると、アラビア語やヘブライ語のロケールで表示が崩れます。
  • 改行モードの確認不足 — 狭いコンテナ(リスト、サイドバー)では、誤ったlineBreakModeが単語の切り捨てを引き起こします。byWordWrappingを使用し、特定のロケールのコンテキストで長い単語を確認してください。
  • 異なるParagraphStyleを持つSpannableの混在 — SPAN_PARAGRAPHを使用してSpannableを設定する場合、段落の境界を正しく計算することが重要です。開始/終了位置が実際の段落の境界と一致しないと、スタイルが無視されます。
  • 忘れられたベースライン配置 — 固定のlineHeight(minimumLineHeight)でParagraphStyleを使用する場合、ベースラインテキスト配置が有効になっていることを確認してください。iOSでは、これにlabel.baselineAdjustment = .alignBaselinesが使用されます。

UX Collective — Common Typography Bugs in Mobile Apps(2025)によると、ParagraphStyleの問題はモバイルアプリケーションのすべてのタイポグラフィバグの18%を占めています。最も深刻なケースは、誤ったparagraphSpacingが異なる行でテキストの重なりを引き起こしたり、RTLロケールがLTRインデントで表示されたりする場合です。さまざまな言語のテスト文字列を使用して、ParagraphStyleパラメータごとに単体テストを作成することをお勧めします。

よくある質問

iOSでParagraphStyleとTextStyleの違いは何ですか?

NSMutableParagraphStyleは段落書式(配置、インデント、行間隔)を管理し、TextStyleは文字属性(フォント、色、サイズ)を管理します。どちらもNSAttributedStringを介して適用されます。ParagraphStyleは段落レベルで機能し、TextStyleは文字レベルで機能します。1つの段落に複数のTextStyleインスタンスが存在できますが、ParagraphStyleは段落ごとに1つだけです。

Jetpack Composeで最初の行のインデントを設定するには?

Jetpack Composeでは、最初の行のインデントはTextStyle内のTextIndentを介して設定されます:TextStyle(textIndent = TextIndent(firstLine = 16.sp))。値はテキストとともに拡大縮小するためにspで指定する必要があります。複数行のテキストの場合、インデントは新しい段落( 文字)を開始する各行に適用されます。最初の段落には常にインデントが適用されます。

SwiftUIで段落間隔を設定するには?

SwiftUIには、paragraphSpacingに直接相当するものはありません。段落間隔には、NSMutableParagraphStyleとparagraphSpacingプロパティを使用したAttributedString(iOS 15+)を使用してください。または、Text("...\n\n...")で段落を区切り、テキストブロック間に.padding()を追加します。複雑なタイポグラフィシナリオでは、UILabelRepresentableを介してNSAttributedStringを使用します。

Android TextViewでparagraphSpacingが機能しないのはなぜですか?

AndroidのTextViewにはparagraphSpacingプロパティがありません — これはLeadingMarginSpanを使用したSpannableString、またはカスタムLineBackgroundSpanを介して設定されます。行間隔にはsetLineSpacingを使用してください。段落間隔には、追加の で段落を区切るか、複数のTextViewインスタンスで構成されたコンテナを使用します。

ParagraphStyleはモバイルアプリのアクセシビリティにどのように影響しますか?

適切なParagraphStyleはアクセシビリティを向上させます:十分なparagraphSpacingは、認知障害のあるユーザーが段落の境界をよりよく識別するのに役立ちます。WCAG 2.2は段落の視覚的な分離(インデントまたは間隔)を推奨しています。ParagraphSpacingは1.5 × line-height以上にする必要があります。RTLロケールでは、インデントが正しくミラーリングされていることを確認してください。

まとめ

  • ParagraphStyle — 段落書式設定ルールのセット:配置、インデント、行間および段落間の間隔。
  • iOS — 14以上のパラメータを持つNSMutableParagraphStyle、NSAttributedStringを介して適用。SwiftUIではAttributedString(iOS 15+)。
  • Android View — ParagraphStyle実装(AlignmentSpan、LeadingMarginSpan)を使用したSpannableString。
  • Android Compose — TextStyle.textAlign、lineHeight、textIndent、改行制御のためのLineBreak。
  • Flutter — 行の高さ固定のためのTextStyle.height、TextAlign、TextHeightBehavior、StrutStyleの組み合わせ。
  • ローカライゼーション — RTLロケールサポートには自然配置を使用。両方のレイアウトでインデントを確認。
  • よくある間違い — 自然配置の代わりのハードコードされた配置、paragraphSpacingBeforeの無視、狭いコンテナでの誤ったlineBreakMode。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください