見出し画像

Now In REALITY Tech #115 ComposeのTextがHTMLに対応したので使ってみた

こんにちは、Androidエンジニアのtkcです。
最近は社会の理想的な制度について思いを馳せています。

先日のGoogle I/O 2024の記事を読んでいると、下記の記事を見つけました。

Text
Text now supports inline links and basic HTML formatting via the new AnnotatedString.fromHtml() extension. This converts basic HTML formatting, including links to an AnnotatedString, which can then be rendered by Compose.

https://android-developers.googleblog.com/2024/05/whats-new-in-jetpack-compose-at-io-24.html

ちょうど去年自分が書いたHTMLをTextで扱う機能がComposeのTextに実装されているようなので、詳細を調べてみました。

実際に使ってみる

まずはテキストにHTMLタグを反映する

公式ドキュメント

ChangeLogをみると1.7.0-alpha07でAnnotatedStringにfromHtmlのメソッドが追加された様子

Stable最新の1.6.8には追加されていないので、とりあえずベータリリース最新の1.7.0-beta04を使う


// First, download a string as a plain text using one of the resources' methods. At this stage
// you will be handling plurals and formatted strings in needed. Moreover, the string will be
// resolved with respect to the current locale and available translations.
val string = stringResource(id = R.string.tagged_text))

// Next, convert a string marked with HTML tags into AnnotatedString to be displayed by Text
val styledAnnotatedString = AnnotatedString.fromHtml(htmlString = string)

BasicText(styledAnnotatedString)
    <string name="tagged_text"><a href="https://reality.app"> REALITY </a> へようこそ!!!!!!<br/><font color="RED">123456</font><big>7890</big>1234567890</string>

とりあえずドキュメントに書いてあるようにやってみると…

反映されてない!

前回やったときにHTMLエスケープしないとだめだったような記憶を思い出しながらドキュメントを見ていると、やはりHTMLエスケープは必要と書いてあった。

If you define your string in the resources, make sure to use HTML-escaped opening brackets "<" instead of "<".

https://developer.android.com/reference/kotlin/androidx/compose/ui/text/AnnotatedString.Companion#(androidx.compose.ui.text.AnnotatedString.Companion).fromHtml(kotlin.String,androidx.compose.ui.text.TextLinkStyles,androidx.compose.ui.text.LinkInteractionListener)

詳しくはResourceのほうのドキュメントにより詳しく書いてあった

そこでリソースでHTMLエスケープをしてみると…

<string name="tagged_text_with_escape">&lt;a href="https://reality.app"> REALITY &lt;/a> へようこそ!!!!!!&lt;br>123456&lt;big>&lt;font color="RED">7890&lt;/font>&lt;/big>1234567890</string>

反映されました

反映された!

リンクをクリックで開く

AnnotatedStringにlinkInteractionListenerという引数があり、
説明を見ると下記のように書いてあるのでリンクを検出してクリック時にブラウザでリンクを開いてくれるのかなと思いました。

a listener that will be attached to links that are present in the string and triggered when user clicks on those links. When set to null, which is a default, the system will try to open the corresponding links with the androidx.compose.ui.platform.UriHandler composition local

AnnotatedString.Companion  |  Android Developers developer.android.com
    val localUriHandler = LocalUriHandler.current
    val styledAnnotatedString = AnnotatedString.fromHtml(
        htmlString = string,
        linkStyles = TextLinkStyles(
            style = SpanStyle(
                color = Color.Blue,
            )
        ),
        linkInteractionListener = { annotation ->
            // Toast.makeText(context,"hoge", Toast.LENGTH_SHORT).show() // クリックしてもここの処理が走らない
            // val url = annotation as? LinkAnnotation.Url ?: return@fromHtml
            // localUriHandler.openUri(url.url)
        }

そこでこのコードでAnnotatedStringを書いてみたのですが、
<a>タグで囲ったREALITYの部分のスタイルが変わることも、クリックでリンクが開かれることもありませんでした。

変化なし

クリック時にlinkInteractionListenerの処理が走らないので、<a>タグで囲った部分がリンクとして認識されていないようです。
<a>タグではなく他のタグが必要なのかと疑いましたが、ドキュメントに手がかりを見つけることができませんでした。
ViewのTextでは<a>タグでリンクを開くことができたので、<a>が使えると思っていたのですが、ComposeのTextではリンクを開くことはできませんでした。
まだこの機能はBeta版なので、今後なにか変更があるかもしれませんが
現状ではこのような挙動であることがわかりました。

まとめ

  • AnnotatedStringにfromHtmlというメソッドが追加され、ComposeのTextでもHTMLが使えるようになった

  • そのため、以前ブログに書いたようなAndroidViewをつかってViewのTextを使う必要がなくなった

  • 文言リソースから取得する場合はHTMLエスケープが必要なのはViewのときと変わらず

  • ViewのTextではリンクとして動作した<a>がComposeでは現状リンクとして動作しない

感想

AndroidViewを使わなくて良くなったのでより簡単になったのは良いのですが、
依然リソースではHTMLエスケープが必要であるのと、
<a>タグがリンクにならないようなので、現状ちょっと使いにくいかなと思いました。
今後<a>タグをつけるだけでブラウザが開くようになったらかなり便利になるんじゃないかと思うので期待して待ちましょう。