前言 之前使用的Markdown组件,但是显示效果不太好,自定义样式也比较麻烦。
这里我们自定义WebView来加载Markdown文本。
添加依赖 这个主要用于使用模板生成HTML
1 2 3 dependencies { implementation 'com.x5dev:chunk-templates:3.6.2' }
添加模板 JS assets/js 中添加 marked.min.js 这个用于渲染md文本。
下载地址
https://js.cybozu.cn/markedjs/v0.3.5/marked.min.js
模板 模板文件要放在src/main/assets/themes文件夹下
注意文件必须以.chtml作为后缀
assets/themes 中添加 md_view.chtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 <!DOCTYPE html > <html > <head > <meta charset ="utf-8" /> <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > AI</title > <script type ="text/javascript" src ="file:///android_asset/js/marked.min.js" > </script > </head > <body > <div id ="main" > <div class ="hide_div" > {$mMdStr}</div > <div class ="md_div" > </div > </div > <style > body { margin: 0; padding: 0; background-color: transparent; overflow: hidden; } .hide_div { display: none; } .md_div { width: 100%; line-height: 150%; color : #333 ; } </style > <script type ="text/javascript" > function renderMarkdown ( ) { var mdStr = document .querySelector('.hide_div' ).innerHTML; var html = marked.parse(mdStr); document .querySelector('.md_div' ).innerHTML = html; } document .addEventListener('DOMContentLoaded' , function ( ) { renderMarkdown() }); </script > </body > </html >
自定义组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import android.annotation .SuppressLintimport android.content.Contextimport android.graphics.Colorimport android.util.AttributeSetimport android.webkit.WebSettingsimport android.webkit.WebViewimport com.x5.template.Chunkimport com.x5.template.Themeimport com.x5.template.providers.AndroidTemplates@SuppressLint("SetJavaScriptEnabled" ) public class ZMdView @JvmOverloads constructor ( context: Context, attrs: AttributeSet? = null , defStyleAttr: Int = 0 ) : WebView(context, attrs, defStyleAttr) { private val TAG_TP_NAME: String = "md_view" private var mMdStr: String = "" init { settings.allowFileAccess = true settings.javaScriptEnabled = true settings.cacheMode = WebSettings.LOAD_NO_CACHE settings.displayZoomControls = false settings.builtInZoomControls = false settings.setSupportZoom(false ) settings.useWideViewPort = true setBackgroundColor(Color.TRANSPARENT) } fun setMdStr (mdStr: String ) { this .mMdStr = mdStr loadHTML() } private fun getChunk () : Chunk { return Theme(AndroidTemplates(context)).makeChunk(TAG_TP_NAME) } private fun loadHTML () { val mChunk: Chunk = getChunk() mChunk.set ("mMdStr" , mMdStr) this .loadDataWithBaseURL(null , mChunk.toString(), "text/html" , "utf-8" , "about:blank" ) } }
Compose封装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import android.view.ViewGroupimport android.webkit.WebViewClientimport androidx.compose.runtime.Composableimport androidx.compose.ui.Modifierimport androidx.compose.ui.viewinterop.AndroidViewimport cn.psvmc.zmdview.ZMdView@Composable fun ZMdViewComp ( htmlContent: String , modifier: Modifier = Modifier ) { AndroidView( modifier = modifier, factory = { context -> val mdView = ZMdView(context).apply { webViewClient = WebViewClient() } mdView.layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ) mdView }, update = { mdView -> mdView.setMdStr(htmlContent) } ) }
使用 1 ZMdViewComp(htmlContent = "## title" )