forked from androidx/androidx
-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add method for creating AnnotatedString from HTML tagged string
This method uses HtmlCompat.fromHtml under the hood. Note that unlike getText(resourceId), it doesn't handle custom annotation tags <annotation> and therefore needs to be handled separately. At the same time, getText(resourceId) doesn't support formatting. The method will be used like so: getString(R.string.example).parseAsHtml() In the future I'm planning to extend parseAsHtml with links styling and links click handler objects. Also note that original HtmlCompat.fromHtml accepts flags which we should consider exposing in the future. Test: demo Test: added tests AnnotatedStringFromHtmlTest Relnote: "Added `parseAsHtml` method for styled strings: it allows to convert a string marked with HTML tags into AnnotatedString. Note that not all tags are supported, for example you won't be able to display bullet lists yet." Change-Id: I84d3d1881805e964cea940eb1c68a5bba16f6416
- Loading branch information
Anastasia Soboleva
committed
Mar 18, 2024
1 parent
824114c
commit 932545d
Showing
11 changed files
with
469 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
.../samples/src/main/java/androidx/compose/ui/text/samples/AnnotatedStringFromHtmlSamples.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.ui.text.samples | ||
|
||
import androidx.annotation.Sampled | ||
import androidx.compose.foundation.text.BasicText | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.res.stringResource | ||
import androidx.compose.ui.text.parseAsHtml | ||
|
||
@Composable | ||
@Sampled | ||
fun AnnotatedStringFromHtml() { | ||
// 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.example) | ||
|
||
// Next, convert a string marked with HTML tags into AnnotatedString to be displayed by Text | ||
val styledAnnotatedString = string.parseAsHtml() | ||
|
||
BasicText(styledAnnotatedString) | ||
} |
40 changes: 40 additions & 0 deletions
40
compose/ui/ui-text/samples/src/main/res/values/styled-string-for-sample.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- | ||
Copyright 2024 The Android Open Source Project | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
--> | ||
|
||
<resources> | ||
<string name="example" translatable="false"> | ||
<b>bold</b> | ||
<i>italic</i> | ||
<big>big</big> | ||
<small>small</small> | ||
<font face="monospace">monospace</font> | ||
<font face="serif">serif</font> | ||
<font face="sans_serif">sans_serif</font> | ||
<font face="cursive">cursive</font> | ||
<font color="#00ff00">green</font> | ||
<tt>monospace</tt> | ||
<sup>superscript</sup> | ||
<strike>strikethrough</strike> | ||
<sub>subscript</sub> | ||
<u>underline</u> | ||
<span style="background-color:#ff0000">span</span> | ||
<p dir="rtl">right to left</p> | ||
<p dir="ltr">left to right</p> | ||
I am <div>div</div> element.<br> | ||
<a href="https://developer.android.com">Link</a> | ||
</string> | ||
</resources> |
20 changes: 20 additions & 0 deletions
20
compose/ui/ui-text/src/androidInstrumentedTest/AndroidManifest.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- Copyright (C) 2024 The Android Open Source Project | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
--> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<application> | ||
<activity android:name="androidx.activity.ComponentActivity" /> | ||
</application> | ||
</manifest> |
104 changes: 104 additions & 0 deletions
104
...rc/androidInstrumentedTest/kotlin/androidx/compose/ui/text/AnnotatedStringFromHtmlTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.ui.text | ||
|
||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.res.stringResource | ||
import androidx.compose.ui.test.junit4.createComposeRule | ||
import androidx.compose.ui.text.font.FontFamily | ||
import androidx.compose.ui.text.font.FontStyle | ||
import androidx.compose.ui.text.font.FontWeight | ||
import androidx.compose.ui.text.style.BaselineShift | ||
import androidx.compose.ui.text.style.TextDecoration | ||
import androidx.compose.ui.unit.em | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import androidx.test.filters.SdkSuppress | ||
import androidx.test.filters.SmallTest | ||
import com.google.common.truth.Truth.assertThat | ||
import org.junit.Rule | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
@SmallTest | ||
@RunWith(AndroidJUnit4::class) | ||
class AnnotatedStringFromHtmlTest { | ||
@get:Rule | ||
val rule = createComposeRule() | ||
|
||
@Test | ||
// pre-N block-level elements were separated with two new lines | ||
@SdkSuppress(minSdkVersion = 24) | ||
fun buildAnnotatedString_fromHtml() { | ||
rule.setContent { | ||
val expected = buildAnnotatedString { | ||
fun add(block: () -> Unit) { | ||
block() | ||
append("a") | ||
pop() | ||
append(" ") | ||
} | ||
fun addStyle(style: SpanStyle) { | ||
add { pushStyle(style) } | ||
} | ||
|
||
add { pushLink(LinkAnnotation.Url("https://example.com")) } | ||
addStyle(SpanStyle(fontWeight = FontWeight.Bold)) | ||
addStyle(SpanStyle(fontSize = 1.25.em)) | ||
append("\na\n") // <div> | ||
addStyle(SpanStyle(fontFamily = FontFamily.Serif)) | ||
addStyle(SpanStyle(color = Color.Green)) | ||
addStyle(SpanStyle(fontStyle = FontStyle.Italic)) | ||
append("\na\n") // <p> | ||
addStyle(SpanStyle(textDecoration = TextDecoration.LineThrough)) | ||
addStyle(SpanStyle(fontSize = 0.8.em)) | ||
addStyle(SpanStyle(background = Color.Red)) | ||
addStyle(SpanStyle(baselineShift = BaselineShift.Subscript)) | ||
addStyle(SpanStyle(baselineShift = BaselineShift.Superscript)) | ||
addStyle(SpanStyle(fontFamily = FontFamily.Monospace)) | ||
addStyle(SpanStyle(textDecoration = TextDecoration.Underline)) | ||
} | ||
|
||
val actual = stringResource(androidx.compose.ui.text.test.R.string.html).parseAsHtml() | ||
|
||
assertThat(actual.text).isEqualTo(expected.text) | ||
assertThat(actual.spanStyles).containsExactlyElementsIn(expected.spanStyles).inOrder() | ||
assertThat(actual.paragraphStyles) | ||
.containsExactlyElementsIn(expected.paragraphStyles) | ||
.inOrder() | ||
assertThat(actual.getStringAnnotations(0, actual.length)) | ||
.containsExactlyElementsIn(expected.getStringAnnotations(0, expected.length)) | ||
.inOrder() | ||
assertThat(actual.getLinkAnnotations(0, actual.length)) | ||
.containsExactlyElementsIn(expected.getLinkAnnotations(0, expected.length)) | ||
.inOrder() | ||
} | ||
} | ||
|
||
@Test | ||
fun formattedString_withStyling() { | ||
rule.setContent { | ||
val actual = stringResource( | ||
androidx.compose.ui.text.test.R.string.formatting, | ||
"computer" | ||
).parseAsHtml() | ||
assertThat(actual.text).isEqualTo("Hello, computer!") | ||
assertThat(actual.spanStyles).containsExactly( | ||
AnnotatedString.Range(SpanStyle(fontWeight = FontWeight.Bold), 7, 15) | ||
) | ||
} | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
compose/ui/ui-text/src/androidInstrumentedTest/res/values/styled-string-for-test.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- | ||
Copyright 2024 The Android Open Source Project | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
--> | ||
|
||
<resources> | ||
<string name="html" translatable="false"> | ||
<a href="https://example.com">a</a> | ||
<b>a</b> | ||
<big>a</big> | ||
<div>a</div> | ||
<font face="serif">a</font> | ||
<font color="#00ff00">a</font> | ||
<i>a</i> | ||
<p>a</p> | ||
<s>a</s> | ||
<small>a</small> | ||
<span style="background-color:red">a</span> | ||
<sub>a</sub> | ||
<sup>a</sup> | ||
<tt>a</tt> | ||
<u>a</u> | ||
</string> | ||
<string name="formatting">Hello, <b>%s</b>!</string> | ||
</resources> |
Oops, something went wrong.