使用撰写文本链接

问题描述

我找不到如何使用 Jetpack Compose 链接我的 Text()

在撰写之前,我所要做的就是:

Linkify.addLinks(myTextView,Linkify.EMAIL_ADDRESSES or Linkify.WEB_URLS)

显然,我的 TextView 中包含的所有链接都变成了可点击的链接。

重要提示:Text 的内容来自 API,链接没有固定位置,内容可能包含多个链接。

我想在使用 Jetpack Compose 时保持这种行为,但我找不到任何有关这样做的信息。

有人知道吗?

解决方法

您可以使用 AnnotatedString 来实现此行为。

文档:https://developer.android.com/reference/kotlin/androidx/compose/ui/text/AnnotatedString

另外,这个可以帮到你:

AutoLink for Android Compose Text

,

如果有人正在寻找解决方案,以下内容将使您的文本中的任何链接都可点击并设置样式:

@Composable
fun LinkifyText(text: String,modifier: Modifier = Modifier) {
    val uriHandler = LocalUriHandler.current
    val layoutResult = remember {
        mutableStateOf<TextLayoutResult?>(null)
    }
    val linksList = extractUrls(text)
    val annotatedString = buildAnnotatedString {
        append(text)
        linksList.forEach {
            addStyle(
                    style = SpanStyle(
                            color = Color.Companion.Blue,textDecoration = TextDecoration.Underline
                    ),start = it.start,end = it.end
            )
            addStringAnnotation(
                    tag = "URL",annotation = it.url,end = it.end
            )
        }
    }
    Text(text = annotatedString,style = MaterialTheme.typography.body1,modifier = modifier.pointerInput(Unit) {
    detectTapGestures { 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 }
    )
}

private val urlPattern: Pattern = Pattern.compile(
        "(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)"
                + "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*"
                + "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",Pattern.CASE_INSENSITIVE or Pattern.MULTILINE or Pattern.DOTALL
)

fun extractUrls(text: String): List<LinkInfos> {
    val matcher = urlPattern.matcher(text)
    var matchStart: Int
    var matchEnd: Int
    val links = arrayListOf<LinkInfos>()

    while (matcher.find()) {
        matchStart = matcher.start(1)
        matchEnd = matcher.end()

        var url = text.substring(matchStart,matchEnd)
        if (!url.startsWith("http://") && !url.startsWith("https://"))
            url = "https://$url"

        links.add(LinkInfos(url,matchStart,matchEnd))
    }
    return links
}

data class LinkInfos(
        val url: String,val start: Int,val end: Int
)
,

我认为现在更好的解决方案是使用 textview 创建自己的组件:

package me.sakuraidev;

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

public class main extends JavaPlugin implements CommandExecutor{
    @SuppressWarnings("unused")
    private main Plugin;
    @Override
    public void onEnable(main Plugin) {
        this.Plugin = Plugin;
        Plugin.getCommand("hello").setExecutor(this);
    }
    public boolean onCommand(CommandSender sender,Command cmd,String label,String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage("Sorry,only players can run this command");
            return true;
        }
        Player p = (Player) sender;
        
        if(p.hasPermission("hello.use")) {
            sender.sendMessage("hi");
        } else {
            sender.sendMessage("Sorry,but you don't have permission to use this command");
        }
        return false;
    }
} 

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...