ユーザー操作を有効にする

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")
        }
    }
}

長い文。ユーザーは文全体を選択しようとしましたが、DisableSelection が適用された 2 つの行は選択されませんでした。

テキストのクリック位置を取得する

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)
        }
    })
}