テキストは UI の主要な構成要素です。Jetpack Compose を使用すると、テキストの表示や入力を簡単に行うことができます。Compose では構成要素のコンポジションを利用できるため、特定のコンポーザブルの設計とロジックを意図したとおりに機能させるにあたり、プロパティやメソッドを上書きしたり、大きなクラスを拡張したりする必要はありません。
Compose には、テキストの表示とユーザー入力の処理に最低限必要な BasicText
と BasicTextField
がベースとして用意されています。その上位レベルでは、マテリアル デザイン ガイドラインに沿ったコンポーザブルである Text
と TextField
を利用できます。Android ユーザーに適切な外観と操作感を提供できるほか、多くのコードを書かなくても簡単にカスタマイズできるオプションも利用できるため、これらのコンポーザブルを使用することをおすすめします。
テキストの表示
テキストを表示するための最も基本的な方法は、引数として String
を指定して Text
コンポーザブルを使用することです。
@Composable
fun SimpleText() {
Text("Hello World")
}
リソースを使用してテキストを表示する
Text
の値をハードコードするのではなく、文字列リソースを使用することをおすすめします。これにより、Android ビューと同じ文字列を共有できるだけでなく、アプリの国際化もしやすくなります。
@Composable
fun StringResourceText() {
Text(stringResource(R.string.hello_world))
}
テキストのスタイル設定
Text
コンポーザブルには、コンテンツのスタイル設定を行うためのオプションのパラメータが複数用意されています。以下に、テキストに関する最も一般的なユースケースに対応するパラメータを示します。Text
のすべてのパラメータを確認するには、Compose Text ソースコードをご覧ください。
これらのパラメータを設定すると、テキスト値全体にスタイルが適用されます。同じ行や段落内に複数のスタイルを適用する必要がある場合は、複数のインライン スタイルのセクションをご覧ください。
テキストの色を変更する
@Composable
fun BlueText() {
Text("Hello World", color = Color.Blue)
}
文字サイズを変更する
@Composable
fun BigText() {
Text("Hello World", fontSize = 30.sp)
}
テキストを斜体にする
テキストを斜体にするには fontStyle
パラメータを使用します(または別の FontStyle
を設定します)。
@Composable
fun ItalicText() {
Text("Hello World", fontStyle = FontStyle.Italic)
}
テキストを太字にする
テキストを太字にするには、fontWeight
パラメータを使用します(または別の FontWeight
を設定します)。
@Composable
fun BoldText() {
Text("Hello World", fontWeight = FontWeight.Bold)
}
テキストの配置
textAlign
パラメータを使用すると、Text
コンポーザブルの面積内でのテキストの配置を設定できます。
デフォルトでは、Text
はコンテンツの値に応じて自然なテキストの配置を選択します。
Text
コンテナの左端: ラテン文字、キリル文字、ハングルなど、左から右に記述するアルファベットの場合Text
コンテナの右端: アラビア語やヘブライ語など、右から左に記述するアルファベットの場合
@Preview(showBackground = true)
@Composable
fun CenterText() {
Text("Hello World", textAlign = TextAlign.Center,
modifier = Modifier.width(150.dp))
}
Text
コンポーザブルのテキストの配置を手動で設定する場合は、TextAlign.Left
や TextAlign.Right
の代わりに TextAlign.Start
や TextAlign.End
を使用します。これにより、使用する言語のテキストの向きに応じて、テキストが Text
コンポーザブルの適切な側に解決されます。たとえば、TextAlign.End
では、フランス語テキストは右側、アラビア語テキストは左側に配置されます。一方、TextAlign.Right
では、使用されているアルファベットの種類にかかわらず、テキストが右側に配置されます。
シャドウ
style
パラメータを使用すると、TextStyle
型のオブジェクトを設定し、複数のパラメータ(シャドウなど)を構成できます。Shadow
は、シャドウの色、オフセット、Text
に対するシャドウの相対位置、ぼかしの程度を表すぼかし半径を受け取ります。
@Preview(showBackground = true)
@Composable
fun TextShadow() {
val offset = Offset(5.0f, 10.0f)
Text(
text = "Hello world!",
style = TextStyle(
fontSize = 24.sp,
shadow = Shadow(
color = Color.Blue,
offset = offset,
blurRadius = 3f
)
)
)
}
フォントの操作
Text
には、コンポーザブルで使用されるフォントを設定するための fontFamily
パラメータを指定できます。デフォルトでは、Serif、Sans Serif、Monospace、Cursive のフォント ファミリーが含まれています。
@Composable
fun DifferentFonts() {
Column {
Text("Hello World", fontFamily = FontFamily.Serif)
Text("Hello World", fontFamily = FontFamily.SansSerif)
}
}
fontFamily
属性を使用して、res/font
フォルダで定義されているカスタムのフォントと書体を操作できます。
font フォルダの図 " class="l10n-absolute-url-src screenshot" l10n-attrs-original-order="src,alt,width,class" src="https://developer.android.com/static/images/jetpack/compose/text-font-folder.png" width="400" />
次の例は、これらのフォント ファイルに基づき、Font
関数を使用して、fontFamily
を定義する方法を示しています。
val firaSansFamily = FontFamily(
Font(R.font.firasans_light, FontWeight.Light),
Font(R.font.firasans_regular, FontWeight.Normal),
Font(R.font.firasans_italic, FontWeight.Normal, FontStyle.Italic),
Font(R.font.firasans_medium, FontWeight.Medium),
Font(R.font.firasans_bold, FontWeight.Bold)
)
最後に、この fontFamily
を Text
コンポーザブルに渡すことができます。fontFamily
には、異なる太さを含めることが可能です。その場合は、次のように手動で fontWeight
を設定して、テキストに適した太さを選択します。
Column {
Text(..., fontFamily = firaSansFamily, fontWeight = FontWeight.Light)
Text(..., fontFamily = firaSansFamily, fontWeight = FontWeight.Normal)
Text(
..., fontFamily = firaSansFamily, fontWeight = FontWeight.Normal,
fontStyle = FontStyle.Italic
)
Text(..., fontFamily = firaSansFamily, fontWeight = FontWeight.Medium)
Text(..., fontFamily = firaSansFamily, fontWeight = FontWeight.Bold)
}
アプリ全体のタイポグラフィを設定する方法については、テーマのドキュメントをご覧ください。
1 つのテキストに複数のスタイルを設定する
同じ Text
コンポーザブルに複数のスタイルを設定するには、AnnotatedString
を使用する必要があります。これは、任意のアノテーションのスタイルでアノテーションを付けることができる文字列です。
AnnotatedString
は、以下を含むデータクラスです。
Text
値SpanStyleRange
のList
(テキスト値内の位置範囲を使用したインライン スタイル設定と同等です)ParagraphStyleRange
のList
(テキストの配置、テキスト方向、行の高さ、テキストのインデント スタイルを指定します)
TextStyle
は Text
コンポーザブルで使用され、SpanStyle
と ParagraphStyle
は AnnotatedString
で使用されます。
SpanStyle
と ParagraphStyle
の違いは、ParagraphStyle
は段落全体に適用できるのに対し、SpanStyle
は文字単位で適用できる点にあります。テキストの一部を ParagraphStyle
でマークすると、その部分は先頭と末尾にラインフィードがあるものとして残りのテキストから分離されます。
AnnotatedString
は、タイプセーフなビルダーを使用して buildAnnotatedString
を簡単に作成できます。
@Composable
fun MultipleStylesInText() {
Text(
buildAnnotatedString {
withStyle(style = SpanStyle(color = Color.Blue)) {
append("H")
}
append("ello ")
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold, color = Color.Red)) {
append("W")
}
append("orld")
}
)
}
ParagraphStyle
も同じ方法で設定できます。
@Composable
fun ParagraphStyle() {
Text(
buildAnnotatedString {
withStyle(style = ParagraphStyle(lineHeight = 30.sp)) {
withStyle(style = SpanStyle(color = Color.Blue)) {
append("Hello\n")
}
withStyle(
style = SpanStyle(
fontWeight = FontWeight.Bold,
color = Color.Red
)
) {
append("World\n")
}
append("Compose")
}
}
)
}
最大行数
Text
コンポーザブルに表示する行数を制限するには、maxLines
パラメータを設定します。
@Composable
fun LongText() {
Text("hello ".repeat(50), maxLines = 2)
}
テキスト オーバーフロー
長いテキストを制限する場合は、TextOverflow
を指定することをおすすめします。これは、表示されているテキストが切り捨てられた場合にのみ表示されます。これを行うには、textOverflow
パラメータを設定します。
@Composable
fun OverflowedText() {
Text("Hello Compose ".repeat(50), maxLines = 2, overflow = TextOverflow.Ellipsis)
}
includeFontPadding API と lineHeight API
includeFontPadding
は、フォント指標に基づいてテキストの最初の行の上と最後の行の下にパディングを追加するレガシー プロパティです。Compose 1.2.0 では、includeFontPadding はデフォルトで true に設定されています。
Compose 1.2.0 で非推奨になった API PlatformTextStyle
を使用して、includeFontPadding
を false に設定し(追加のパディングが削除されます)、テキストをさらに調整することをおすすめします。
lineHeight
を設定する機能は新しいものではなく、Android Q 以降で利用できます。Text
の lineHeight
を設定するには、lineHeight
パラメータを使用します。これにより、テキストの各行で行の高さが割り振られます。その後、新しい LineHeightStyle API
を使用して、スペース内でのテキストの配置方法をさらに設定し、空白文字を削除できます。
精度を高めるために、テキストの単位に「sp」(スケール非依存ピクセル)ではなく「em」(相対的なフォントサイズ)を使用して lineHeight
を調整することをおすすめします。適切なテキストの単位の選択方法について詳しくは、こちらをご覧ください。

@Composable
fun AlignedText() {
Text(
text = myText,
style = LocalTextStyle.current.merge(
TextStyle(
lineHeight = 2.5.em,
platformStyle = PlatformTextStyle(
includeFontPadding = false
),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None
)
)
)
)
}
lineHeight
の調整に加えて、テキストを中央に配置してスタイルを設定するには、LineHeightStyle
の試験運用版 API である LineHeightStyle.Alignment
および LineHeightStyle.Trim
(Trim を機能させるには、includeFontPadding
を false に設定する必要があります)での構成を使用します。Alignment と Trim は、テキストの行間にある測定されたスペースを使用し、1 行のテキストやテキストのブロックの一番上の行を含め、すべての行にスペースをさらに適切に割り振ります。
LineHeightStyle.Alignment
は、行の高さによって指定されるスペース内の行の配置方法を定義します。各行内で、テキストを上、下、中央に、または比例して配置できます。LineHeightStyle.Trim
を使用すると、lineHeight
と Alignment の調整から生成された、テキストの 1 行目の上と最後の行の下の追加のスペースを残すか削除できます。次のサンプルは、アライメントが中央に配置されたとき(LineHeightStyle.Alignment.Center
)に、さまざまな LineHeightStyle.Trim
構成で複数行のテキストがどのように表示されるかを示しています。
![]() |
![]() |
LineHeightStyle.Trim.None | LineHeightStyle.Trim.Both |
![]() |
![]() |
LineHeightStyle.Trim.FirstLineTop | LineHeightStyle.Trim.LastLineBottom |
この変更の背景、includeFontPadding がビューシステムでどのように機能していたか、Compose に加えられた変更、新しい LineHeightStyle
API の詳細については、Compose テキストにおけるフォントのパディングの修正に関するブログ投稿をご覧ください。
テーマ設定
テキストのスタイル設定にアプリのテーマを使用する場合は、テーマのドキュメントをご覧ください。
ユーザー操作
Jetpack Compose により、Text
でのきめ細かい操作が可能となり、テキストをコンポーザブル レイアウト全体でより柔軟に選択できるようになりました。テキストでのユーザー操作では、他のコンポーザブル レイアウトとは異なり、Text
コンポーザブルの一部に修飾子を追加することができません。このセクションでは、ユーザー操作を可能にするさまざまな API について説明します。
テキストの選択
コンポーザブルはデフォルトでは選択不可であるため、ユーザーがアプリからテキストを選択してコピーすることはできません。テキストの選択を有効にするには、テキスト要素を SelectionContainer
コンポーザブルでラップする必要があります。
@Composable
fun SelectableText() {
SelectionContainer {
Text("This text is selectable")
}
}
選択可能な領域の特定の部分で選択を無効にすることもできます。それには、選択不可にする部分を DisableSelection
コンポーザブルでラップする必要があります。
@Composable
fun PartiallySelectableText() {
SelectionContainer {
Column {
Text("This text is selectable")
Text("This one too")
Text("This one as well")
DisableSelection {
Text("But not this one")
Text("Neither this one")
}
Text("But again, you can select this one")
Text("And this one too")
}
}
}
テキストのクリック位置を取得する
Text
のクリックをリッスンするには、clickable
修飾子を追加します。ただし、Text
コンポーザブル内でクリック位置を取得して、その位置によって異なるアクションを提供する場合は、代わりに ClickableText
を使用する必要があります。
@Composable
fun SimpleClickableText() {
ClickableText(
text = AnnotatedString("Click Me"),
onClick = { offset ->
Log.d("ClickableText", "$offset -th character is clicked.")
}
)
}
アノテーション付きのクリック
ユーザーが Text
コンポーザブルをクリックしたときに、Text
値の一部に情報を追加することもできます(特定の単語にアタッチされている URL をブラウザで開く、など)。そのためには、タグ(String
)、アイテム(String
)、テキスト範囲をパラメータとして取るアノテーションを追加する必要があります。AnnotatedString
から、これらのアノテーションをタグまたはテキスト範囲でフィルタできます。次に例を示します。
@Composable
fun AnnotatedClickableText() {
val annotatedText = buildAnnotatedString {
append("Click ")
// We attach this *URL* annotation to the following content
// until `pop()` is called
pushStringAnnotation(tag = "URL",
annotation = "https://developer.android.com")
withStyle(style = SpanStyle(color = Color.Blue,
fontWeight = FontWeight.Bold)) {
append("here")
}
pop()
}
ClickableText(
text = annotatedText,
onClick = { offset ->
// We check if there is an *URL* annotation attached to the text
// at the clicked position
annotatedText.getStringAnnotations(tag = "URL", start = offset,
end = offset)
.firstOrNull()?.let { annotation ->
// If yes, we log its value
Log.d("Clicked URL", annotation.item)
}
}
)
}
テキストの入力と変更
TextField
を使用すると、ユーザーがテキストの入力や変更を行えるようになります。TextField
の実装には次の 2 つのレベルがあります。
TextField
はマテリアル デザインの実装であり、次のようなマテリアル デザイン ガイドラインに沿っているため、この実装を選択することをおすすめします。BasicTextField
を使用すると、ユーザーはハードウェア キーボードまたはソフトウェア キーボードを使用してテキストを編集できます。ただし、ヒントやプレースホルダのような装飾は用意されていません。
@Composable
fun SimpleFilledTextFieldSample() {
var text by remember { mutableStateOf("Hello") }
TextField(
value = text,
onValueChange = { text = it },
label = { Text("Label") }
)
}
@Composable
fun SimpleOutlinedTextFieldSample() {
var text by remember { mutableStateOf("") }
OutlinedTextField(
value = text,
onValueChange = { text = it },
label = { Text("Label") }
)
}
TextField のスタイル設定
TextField
と BasicTextField
は、カスタマイズ用のパラメータを多数共有しています。TextField
の完全なリストについては、TextField
ソースコードをご覧ください。有用なパラメータの一部を以下に示します。
singleLine
maxLines
textStyle
@Composable
fun StyledTextField() {
var value by remember { mutableStateOf("Hello\nWorld\nInvisible") }
TextField(
value = value,
onValueChange = { value = it },
label = { Text("Enter text") },
maxLines = 2,
textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
modifier = Modifier.padding(20.dp)
)
}
デザインにマテリアルの TextField または OutlineTextField が必要な場合は、BasicTextField
ではなく TextField
をおすすめします。ただし、マテリアル仕様の装飾を必要としないデザインを構築する場合には、BasicTextField
を使用する必要があります。
キーボード オプション
TextField
を使用すると、キーボード レイアウトなどのキーボード構成オプションを設定できます。また、キーボードでサポートされている場合は、自動修正を有効にすることも可能です。ソフトウェア キーボードが次に示すオプションに対応していない場合、一部のオプションは保証されない可能性があります。サポートされているキーボード オプションのリストを次に示します。
capitalization
autoCorrect
keyboardType
imeAction
形式
TextField
を使用すると、入力値に VisualTransformation
を設定できます。たとえば、パスワードの文字を *
で置き換えたり、クレジット カード番号の 4 桁の数字ごとにハイフンを挿入したりできます。
@Composable
fun PasswordTextField() {
var password by rememberSaveable { mutableStateOf("") }
TextField(
value = password,
onValueChange = { password = it },
label = { Text("Enter password") },
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
)
}
その他の例については、VisualTransformSamples ソースコードをご覧ください。
入力のクリーニング
テキストを編集する場合の一般的なタスクは、先頭の文字列を削除することか、あるいは変更されるたびに入力文字列を変換することです。
一つのモデルとして、onValueChange
ごとにキーボードから任意の大幅な編集がなされる場合を考える必要があります。たとえば、ユーザーが自動修正や、単語の絵文字への置き換えなど、高度な編集機能を使用する場合です。これを適切に処理するには、今回 onValueChange
に渡されるテキストは、前回または次回 onValueChange
に渡される値と無関係であるという前提で、変換ロジックを作成します。
また、先頭のゼロを禁止するテキスト フィールドを実装するには、値が変更されるたびに先頭のゼロをすべて削除します。
@Composable
fun NoLeadingZeroes() {
var input by rememberSaveable { mutableStateOf("") }
TextField(
value = input,
onValueChange = { newText ->
input = newText.trimStart { it == '0' }
}
)
}
テキストを削除する際にカーソルの位置を制御するには、状態の一部として TextField
の TextFieldValue
オーバーロードを使用します。
ダウンロード可能なフォント
Compose 1.2-alpha07 以降では、Compose アプリでダウンロード可能なフォント API を使用して Google Fonts を非同期でダウンロードし、アプリで使用することができます。
カスタム プロバイダが提供するダウンロード可能なフォントは、現時点ではサポートされていません。
プログラムを介してダウンロード可能なフォントを使用する
アプリ内からプログラムを介してフォントをダウンロードするには、次の手順を行います。
- 依存関係を追加します。
Groovy
dependencies { ... implementation "androidx.compose.ui:ui-text-google-fonts:1.3.0" }
Kotlin
dependencies { ... implementation("androidx.compose.ui:ui-text-google-fonts:1.3.0") }
- Google Fonts の認証情報で
GoogleFont.Provider
を初期化します。@OptIn(ExperimentalTextApi::class) val provider = GoogleFont.Provider( providerAuthority = "com.google.android.gms.fonts", providerPackage = "com.google.android.gms", certificates = R.array.com_google_android_gms_fonts_certs )
プロバイダが受け取るパラメータは次のとおりです。- Google Fonts のフォント プロバイダの権限
- プロバイダの ID を確認するためのフォント プロバイダ パッケージ
- プロバイダの ID を確認するための、証明書のハッシュセットのリストGoogle Fonts プロバイダに必要なハッシュは、JetChat サンプルアプリの
font_certs.xml
ファイルで確認できます。
ExperimentalTextApi
アノテーションを追加する必要があります。 FontFamily
を次のように定義します。import androidx.compose.ui.text.googlefonts.GoogleFont import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.googlefonts.Font val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider) )
フォントの他のパラメータをクエリすることもできます。たとえば、weight と style にはFontWeight
とFontStyle
をそれぞれ使用します。import androidx.compose.ui.text.googlefonts.GoogleFont import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.googlefonts.Font val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold, style = FontStyle.Italic) )
- コンポーズ可能な Text 関数で使用できるように
FontFamily
を設定します。Text( fontFamily = fontFamily, text = "Hello World!" )
FontFamily
を使用するタイポグラフィを定義することもできます。val MyTypography = Typography( body1 = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = ... ), body2 = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.Bold, letterSpacing = ... ), h4 = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.SemiBold ... ), ...
次に、タイポグラフィをアプリのテーマに設定します。MyAppTheme( typography = MyTypography ) { ...
Compose でダウンロード可能なフォントをマテリアル 3 と一緒に実装するアプリの例については、JetChat サンプルアプリをご覧ください。
代替フォント
フォントが適切にダウンロードされなかった場合に備えて、フォントの代替チェーンを指定できます。たとえば、ダウンロード可能なフォントを次のように定義したとします。
import androidx.compose.ui.text.googlefonts.Font val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider), Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold) )
両方のウェイトのデフォルト フォントを次のように定義できます。
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.googlefonts.Font val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider), Font(resId = R.font.my_font_regular), Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold), Font(resId = R.font.my_font_regular_bold, weight = FontWeight.Bold) )
正しいインポートを追加していることを確認してください。
このように FontFamily
を定義すると、2 つのチェーン(ウェイトごとに 1 つ)を含む FontFamily
が作成されます。読み込みメカニズムでは、まずオンライン フォントを解決し、次にローカルの R.font
リソース フォルダにあるフォントを解決しようとします。
実装のデバッグ
フォントが正しくダウンロードされていることを確認するには、デバッグ コルーチン ハンドラを定義します。ハンドルを使用すると、フォントが非同期でロードされなかった場合に実行する動作を指定できます。
まず、CoroutineExceptionHandler
を作成します。
val handler = CoroutineExceptionHandler { _, throwable ->
// process the Throwable
Log.e(TAG, "There has been an issue: ", throwable)
}
次に、それを createFontFamilyResolver
メソッドに渡して、リゾルバが新しいハンドラを使用できるようにします。
CompositionLocalProvider(
LocalFontFamilyResolver provides createFontFamilyResolver(LocalContext.current, handler)
) {
Column {
Text(
text = "Hello World!",
style = MaterialTheme.typography.body1
)
}
}
プロバイダの isAvailableOnDevice
API を使用して、プロバイダが利用可能であり、証明書が正しく構成されているかどうかをテストすることもできます。このテストを実行するには isAvailableOnDevice
メソッドを呼び出します。プロバイダが正しく構成されていない場合には false が返されます。
val context = LocalContext.current
LaunchedEffect(Unit) {
if (provider.isAvailableOnDevice(context)) {
Log.d(TAG, "Success!")
}
}
注意点
Google Fonts では、Android で新しいフォントを利用できるようになるまでに数か月かかります。フォントが fonts.google.com に追加されてから、ダウンロード可能なフォント API(ビューシステムまたは Compose)で利用できるようになるまでに時間的なずれがあります。新たに追加されたフォントが、IllegalStateException
でアプリに読み込めない場合があります。デベロッパーがこのエラーと他の種類のフォント読み込みエラーを見分けることができるよう、Compose に例外についての説明メッセージを追加しました。変更内容については、こちらをご覧ください。