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 一起创作吧!🤩

相关推荐
tangweiguo0305198741 分钟前
Android 混合开发实战:统一 View 与 Compose 的浅色/深色主题方案
android
老狼孩111221 小时前
2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发
android·机器人·自动化·lua·脚本开发·懒人精灵·免root开发
打死不学Java代码1 小时前
PaginationInnerInterceptor使用(Mybatis-plus分页)
android·java·mybatis
IT乐手3 小时前
android 解决系统级应用 WebView 加载崩溃的问题
android
Kapaseker3 小时前
Kotlin泛型精解:类型世界的奇幻之旅
android·kotlin
余生大大3 小时前
关于Safari浏览器在ios<16.3版本不支持正则表达式零宽断言的解决办法
ios·正则表达式·safari
顾林海3 小时前
深入探究 Android Native 代码的崩溃捕获机制
android·面试·性能优化
爱分享的程序员4 小时前
前端跨端框架的开发以及IOS和安卓的开发流程和打包上架的详细流程
android·前端·ios
thigh_d4 小时前
uniapp 安卓离线本地打包,Android Studio生成apk包
android·uni-app·android studio
Macle_Chen4 小时前
ios开发中xxx.debug.dylib not found
ios·bug·debug.dylib