前言
之前使用的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.SuppressLint import android.content.Context import android.graphics.Color import android.util.AttributeSet import android.webkit.WebSettings import android.webkit.WebView import com.x5.template.Chunk import com.x5.template.Theme import 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.ViewGroup import android.webkit.WebViewClient import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.viewinterop.AndroidView import 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")
|