Skip to content

Instantly share code, notes, and snippets.

@stevdza-san
Last active September 6, 2024 09:40
Show Gist options
  • Save stevdza-san/ff9dbec0e072d8090e1e6d16e6b73c91 to your computer and use it in GitHub Desktop.
Save stevdza-san/ff9dbec0e072d8090e1e6d16e6b73c91 to your computer and use it in GitHub Desktop.
Embedd a Hyperlink within a Text using Jetpack Compose.
import androidx.compose.foundation.text.ClickableText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.TextUnit
@Composable
fun HyperlinkText(
modifier: Modifier = Modifier,
fullText: String,
linkText: List<String>,
linkTextColor: Color = Color.Blue,
linkTextFontWeight: FontWeight = FontWeight.Medium,
linkTextDecoration: TextDecoration = TextDecoration.Underline,
hyperlinks: List<String> = listOf("https://stevdza-san.com"),
fontSize: TextUnit = TextUnit.Unspecified
) {
val annotatedString = buildAnnotatedString {
append(fullText)
linkText.forEachIndexed { index, link ->
val startIndex = fullText.indexOf(link)
val endIndex = startIndex + link.length
addStyle(
style = SpanStyle(
color = linkTextColor,
fontSize = fontSize,
fontWeight = linkTextFontWeight,
textDecoration = linkTextDecoration
),
start = startIndex,
end = endIndex
)
addStringAnnotation(
tag = "URL",
annotation = hyperlinks[index],
start = startIndex,
end = endIndex
)
}
addStyle(
style = SpanStyle(
fontSize = fontSize
),
start = 0,
end = fullText.length
)
}
val uriHandler = LocalUriHandler.current
ClickableText(
modifier = modifier,
text = annotatedString,
onClick = {
annotatedString
.getStringAnnotations("URL", it, it)
.firstOrNull()?.let { stringAnnotation ->
uriHandler.openUri(stringAnnotation.item)
}
}
)
}
@shivamparihar12
Copy link

Now that ClickableText in Jetpack Compose is deprecated, this is my implementation, of course inspired by @stevdza-san's solution.

import androidx.compose.foundation.text.LinkAnnotation
import androidx.compose.foundation.text.TextLinkStyles
import androidx.compose.foundation.text.withLink
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.TextUnit

@Composable
fun HyperlinkText(
    modifier: Modifier = Modifier,
    text: String,
    linkText: List<String>,
    hyperlinks: List<String>,
    linkTextColor: Color = MaterialTheme.colorScheme.primary,
    linkTextFontWeight: FontWeight = FontWeight.Normal,
    linkTextDecoration: TextDecoration = TextDecoration.Underline,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontFamily: FontFamily = FontFamily.Monospace
) {
    val uriHandler = LocalUriHandler.current

    val annotatedString = buildAnnotatedString {
        var lastIndex = 0
        linkText.forEachIndexed { index, link ->
            val startIndex = text.indexOf(link, lastIndex)
            val endIndex = startIndex + link.length

            if (startIndex > lastIndex) append(text.substring(lastIndex, startIndex))

            val linkUrL = LinkAnnotation.Url(
                hyperlinks[index], TextLinkStyles(
                    SpanStyle(
                        color = linkTextColor,
                        fontSize = fontSize,
                        fontWeight = linkTextFontWeight,
                        textDecoration = linkTextDecoration,
                        fontFamily = fontFamily
                    )
                )
            ) {
                val url = (it as LinkAnnotation.Url).url
                uriHandler.openUri(url)
            }
            withLink(linkUrL) { append(link) }
            append(" ")
            lastIndex = endIndex + 1
        }
        if (lastIndex < text.length) {
            append(text.substring(lastIndex))
        }
        addStyle(
            style = SpanStyle(
                fontSize = fontSize, fontFamily = fontFamily
            ), start = 0, end = text.length
        )
    }
    Text(text = annotatedString, modifier = modifier)
} 

@TDB-star
Copy link

TDB-star commented Sep 6, 2024

Thanks 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment