RtText:我为Kotlin Multiplatform Compose 写了一个富文本显示器

RtText:Kotlin Multiplatform Compose HTML & Markdown 显示组件

由于KMM没有自带的WebView,虽然第三方社区有一个WebView库在维护,但在我使用的过程中发现,由于Kotlin Multiplatform底层原因,导致WebView在IOS设备上,无法与compose组件嵌套滑动。

而我仅仅只是需要显示Html罢了,所以诞生了RtText,一个纯Compose实现的富文本显示器

RtText是Kotlin Multiplatform 库,支持多平台IOS、Android、Destop。

示例

计划

  • 完善Html标签支持
  • 支持Markdown显示

RtText目前支持的HTML标签有:h1,h2,h3,h4,h5,h6,a,b,strong,ol,ul,p,img,table

  • CSS: RtText支持设置简单的CSS属性
  • 扩展标签:RtText支持自定义标签

添加到项目

RtText发布在Maven Central仓库

添加依赖项 到commonMain. 最新版本

kotlin 复制代码
implementation("cn.changjiahong:RtText:<version>")

快速开始

协议链接

kotlin 复制代码
    val license = "勾选即代表你同意本应用<a href=\"https://ex.license.com\"><b>使用协议</b></a>。"

    RtHtml(
        license,
        modifier = Modifier.fillMaxSize(),
        linkAction = { link ->
            openLink(link)
        }
    )

跳转注册

kotlin 复制代码
  val regsiter =
        "你还没有账号?点击跳转<a style=\" color:#ffdd0000\" href=\"register\"><b>注册</b></a>。"
        
   RtHtml(
        regsiter,
        modifier = Modifier.fillMaxSize(),
        linkAction = { tag ->
            when(tag){
                "register" -> goToRegister()
            }
        }
    )

CSS风格

RtText默认提供了一组github风格CSS,你也可以自定义CSS。

kotlin 复制代码
val customCss = """
        .post-md
        {
            width: 100%;
            font-size: 16.8px;
            letter-spacing: 0;
        }
    
        .post-md h1,
        .post-md h2,
        .post-md h3,
        .post-md h4,
        .post-md h5,
        .post-md h6
        {
            color: #000;
            margin: 12px 0;
        }
        .post-md h1
        {
            font-size: 2.5rem;
            line-height: 1.2;
            padding: 24px 0;
        }
        .post-md h2
        {
            font-size: 2rem;
            line-height: 1.2;
            padding: 20px 0;
        }
        .post-md h3
        {
            font-size: 1.75rem;
            line-height: 1.2;
            padding: 18px 0;
        }
        .post-md h4
        {
            font-size: 1.5rem;
            line-height: 1.2;
            padding: 16px 0;
        }
        .post-md h5
        {
            font-size: 1.25rem;
            line-height: 1.2;
            padding: 14px 0;
        }
        .post-md h6
        {
            font-size: 1.125rem;
            line-height: 1.2;
            padding: 12px 0;
        }
        .post-md a
        {
            color: #666;
            box-shadow: 0 2px 0 #ccc;
            /* transition: color ease-in-out .65s, box-shadow ease-in-out .65s; */
        }
    """.trimIndent()

    RtHtml(
        html,
        css = customCss,
        modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()),
        linkAction = {
            println(it)
        }
    )

自定义标签

简单标签处理器

RtText默认支持的标签处理器defaultNodeHandlers,若要扩展新的处理器,则只需要实现NodeHandler并注册即可。

kotlin 复制代码
// 自定义blod标签,支持字体加粗显示
val blod = NodeHandler("blod") { node: Node ->
    val (spanStyle, paragraphStyle) = node.parseStyle()
    withStyle(style = SpanStyle(fontWeight = FontWeight.Bold).merge(spanStyle)) {
        appendChild(node)
    }
}

// nodeHandlers里注册blod
RtHtml(
        html,
        nodeHandlers = mutableListOf(blod).apply { addAll(defaultNodeHandlers) },
        modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()),
        linkAction = {
            println(it)
        }
    )

特殊标签处理器

RtText中若要绘制特殊显示,如img,table等标签,则可实现InlineNodeProcessor处理器。

kotlin 复制代码
// 代码块标签处理器
val code =
    InlineNodeProcessor("code") {
        val param: Param = Json.decodeFromString(it)
        val codeNode = Ksoup.parse(param.contentText).body().firstChild()!!
        Box(modifier = Modifier.fillMaxWidth().wrapContentHeight().background(Color.Yellow)) {
            Text(codeNode.outHtml())
        }
    }

如果需要改变内嵌控件的高度,则可调用handlerContext.updateInlineContent()更新

kotlin 复制代码
val density = LocalDensity.current.density
val fontScale = LocalDensity.current.fontScale
val handlerContext = LocalHandlerContext.current

Box(modifier = Modifier
    .onSizeChanged { size ->
        handlerContext.updateInlineContent(
            param, (size.width / density * fontScale).sp,
            (size.height / density * fontScale).sp,
        )
}){
    Text("")
}

依赖

RtText依赖以下lib,如果你使用了RtText,则不需要再重复添加该库

觉得此存储库有用?

通过加入此存储库的 stargazers 来支持它。⭐ 也可以 Follow Me 一起创作吧!🤩

相关推荐
火柴就是我8 小时前
让我们实现一个更好看的内部阴影按钮
android·flutter
开心就好20259 小时前
UniApp开发应用多平台上架全流程:H5小程序iOS和Android
后端·ios
FunnySaltyFish12 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
开心就好202512 小时前
免 Xcode 的 iOS 开发新选择?聊聊一款更轻量的 iOS 开发 IDE kxapp 快蝎
后端·ios
砖厂小工15 小时前
用 GLM + OpenClaw 打造你的 AI PR Review Agent — 让龙虾帮你审代码
android·github
恋猫de小郭15 小时前
Apple 的 ANE 被挖掘,AI 硬件公开,宣传的 38 TOPS 居然是"数字游戏"?
前端·人工智能·ios
张拭心15 小时前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能
张拭心16 小时前
Android 17 来了!新特性介绍与适配建议
android·前端
Kapaseker18 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
黄林晴18 小时前
Android17 为什么重写 MessageQueue
android