Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoLink for Android Compose Text

Is there any way to use android:autoLink feature on JetPack Compose Text?

I know, that it is maybe not "declarative way" for using this feature in one simple tag/modifier, but maybe there is some easy way for this?

For styling text I can use this way

 val apiString = AnnotatedString.Builder("API provided by")
        apiString.pushStyle(
            style = SpanStyle(
                color = Color.Companion.Blue,
                textDecoration = TextDecoration.Underline
            )
        )
        apiString.append("https://example.com")

        Text(text = apiString.toAnnotatedString())

But, how can I manage clicks here? And would be great, if I programatically say what behaviour I expect from the system (email, phone, web, etc). Like it. works with TextView. Thank you

like image 231
Sirelon Avatar asked Nov 08 '20 14:11

Sirelon


Video Answer


2 Answers

We can achieve Linkify kind of TextView in Android Compose like this example below,

@Composable
fun LinkifySample() {
    val uriHandler = UriHandlerAmbient.current

    val layoutResult = remember {
        mutableStateOf<TextLayoutResult?>(null)
    }

    val text = "API provided by"
    val annotatedString = annotatedString {
        pushStyle(
            style = SpanStyle(
                color = Color.Companion.Blue,
                textDecoration = TextDecoration.Underline
            )
        )
        append(text)
        addStringAnnotation(
            tag = "URL",
            annotation = "https://example.com",
            start = 0,
            end = text.length
        )
    }
    Text(
        fontSize = 16.sp,
        text = annotatedString, modifier = Modifier.tapGestureFilter { offsetPosition ->
            layoutResult.value?.let {
                val position = it.getOffsetForPosition(offsetPosition)
                annotatedString.getStringAnnotations(position, position).firstOrNull()
                    ?.let { result ->
                        if (result.tag == "URL") {
                            uriHandler.openUri(result.item)
                        }
                    }
            }
        },
        onTextLayout = { layoutResult.value = it }
    )
}

In the above example, we can see we give the text and also we use addStringAnnotation to set the tag. And using tapGestureFilter, we can get the clicked annotation.

Finally using UriHandlerAmbient.current we can open the link like email, phone, or web.

Reference : https://www.hellsoft.se/rendering-markdown-with-jetpack-compose/

like image 129
Muthukrishnan Rajendran Avatar answered Sep 20 '22 23:09

Muthukrishnan Rajendran


The most important part of jetpack compose is the compatibility with native android components.

Create a component that use TextView and use it:

@Composable
fun DefaultLinkifyText(modifier: Modifier = Modifier, text: String?) {
    val context = LocalContext.current
    val customLinkifyTextView = remember {
       TextView(context)
    }
    AndroidView(modifier = modifier, factory = { customLinkifyTextView }) { textView ->
        textView.text = text ?: ""
        LinkifyCompat.addLinks(textView, Linkify.ALL)
        Linkify.addLinks(textView, Patterns.PHONE,"tel:",
            Linkify.sPhoneNumberMatchFilter, Linkify.sPhoneNumberTransformFilter)
        textView.movementMethod = LinkMovementMethod.getInstance()
    }
}

How to use:

 DefaultLinkifyText(
    modifier = Modifier
        .fillMaxWidth()
        .wrapContentHeight(),
    text = "6999999 and https://stackoverflow.com/ works fine"
 )
like image 38
Jose Pose S Avatar answered Sep 19 '22 23:09

Jose Pose S