实现给网页中连续添加文本

继上次使用自定义TextView展示内容后,产品觉得效果不太好,不能动态添加分隔线,这不,又要求我做更智能一些,怀着不断学习和为公司着想的理念,我又有了一个大胆的想法:使用跨语言实现。就是使用Html加一些JS代码来实现界面渲染功能。
自从有了ChatGPT,我在开发中有些麻烦和困扰经常也都能被解决掉,这次我就是让ChatGPT帮我写了一个Html代码,实现了一个类似如下界面的功能。


文本与文本之间增加分割线
添加分割线和底部提示文本

自定义textview中添加分割线真心有困难,不能通过Html中的
标签实现,所以我干脆直接使用WebView展示一段文本,文本内容由自己加Html标签实现。

创建一个Html文件,并实现插入文本,控制内容边距等功能

该文件我就全名为:show_text.html吧

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>文本展示</title>
        <style>
            /* 设置body内边距为0 */
            body {
                padding: 0;
                margin: 0;
            }

            /* 设置p标签的左右margin为5 */
            p {
                margin-left: 5px;
                margin-right: 5px;
            }

            /* 定义分隔线样式 */
            .separator {
                border: none; /* 去掉边框 */
                height: 15px; /* 设置高度为15px */
                background-color: #f2f2f2; /* 设置背景颜色为灰色 */
                margin: 0; /* 设置上下边距为10px,左右边距为0 */
                padding: 0;
            }

            /* 定义旋转动画 */
            @keyframes spin {
                0% {
                    transform: rotate(0deg);
                }
                100% {
                    transform: rotate(360deg);
                }
            }

            /* 定义loading图片样式 */
            .loading-img {
                width: 20px; /* 设置图片宽度 */
                height: 20px; /* 设置图片高度 */
                animation: spin 1s linear infinite; /* 应用旋转动画 */
            }

            /* 定义loading布局样式 */
            .loading-layout {
                height: 50px; /* 设置高度为100px */
                /*background-color: white;*/ /* 设置背景颜色为白色 */
                display: flex; /* 使用flex布局 */
                justify-content: center; /* 水平居中 */
                align-items: center; /* 垂直居中 */
            }
        </style>
    </head>
    <body style="">

        <div id="content"></div>
        <script>
            function appendText(text) {
                var div = document.getElementById('content');
                div.innerHTML += text;
                // 计算更新后的内容高度
                // var newHeight = document.body.scrollHeight;
                setTimeout(
                    function(){
                        var newHeight = div.offsetHeight;
                        jsbridge.updateHeight(newHeight);
                    },100
                );
            }

            // 创建loading布局
            function addLoadingLayout() {
                var loadingDiv = document.createElement('div');
                loadingDiv.classList.add('loading-layout'); // 添加loading布局样式

                var spinner = document.createElement('img');
                spinner.src = 'loading_img.png'; // 设置图片路径
                spinner.classList.add('loading-img'); // 添加loading图片样式

                loadingDiv.appendChild(spinner);

                // 创建loading文本
                var loadingText = document.createElement('p');
                loadingText.textContent = '-The End-'; // 设置文本内容
                //loadingText.style.color = 'black'; // 设置文本颜色
                loadingText.style.fontFamily = 'Arial, sans-serif'; // 设置字体
                loadingText.style.display = 'none'; // 默认隐藏文本

                loadingDiv.appendChild(loadingText);

                document.body.appendChild(loadingDiv);

                return {
                    showImage: function() {
                        spinner.style.display = 'block'; // 显示图片
                        loadingText.style.display = 'none'; // 隐藏文本
                    },
                    showText: function() {
                        spinner.style.display = 'none'; // 隐藏图片
                        loadingText.style.display = 'block'; // 显示文本
                    }
                };
            }
            // 创建loading布局并保存引用
            var loadingLayout = addLoadingLayout();
            loadingLayout.showImage();
        </script>
    </body>
</html>

最重要的就是这段代码了

<div id="content"></div>
<script>
        function appendText(text) {
            var div = document.getElementById('content');
            div.innerHTML += text;
            // 计算更新后的内容高度
            // var newHeight = document.body.scrollHeight;
            setTimeout(
                function(){
                    var newHeight = div.offsetHeight;
                    umenovel.updateHeight(newHeight);
                },100
            );
        }
</script>

主要通过调用appendText方法不段往content这个段落中添加文本,并在添加完后获取当前webview中内容的高度。

实现webview加载该html文件

  • 在Activity中布局内加入一个webview组件,用于加载Html文件。
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".book.novelreadmodel.NovelReadActivity">

    <WebView
        android:id="@+id/webview_read"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
  • 在Activity中初始化该WebView,并设置允许使用javascript能力。
public class DemoActivity extends AppCompatActivity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WebView mReadWebView = findViewById(R.id.webview_read);
        // 加入下面两段可以在本webview中显示网页,不会打开跳转到系统浏览器
        mReadWebView.setWebChromeClient(new WebChromeClient() {

        });
        mReadWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
            }
        });

        mReadWebSettings = mReadWebView.getSettings();
        mReadWebSettings.setJavaScriptEnabled(true);
        mReadWebSettings.setSupportZoom(false);
        mReadWebSettings.setBuiltInZoomControls(false);
        mReadWebSettings.setDefaultFontSize(mTextSize);

        // 拉回桥接接口
        ReadModelJsBridge readModelJsBridge = new ReadModelJsBridge();
        mReadWebView.addJavascriptInterface(readModelJsBridge, "jsbridge");
    }
}

桥接对象中处理获取内容高度的回调。如下:

@Keep
public class ReadModelJsBridge {
    /**
     * 更新Html中内容的高度
     */
    @JavascriptInterface
    public void updateHeight(int contentHeight) {
    }
}

webview加载本地html文件

将show_text.html文件放到assets目录下,如果有loading图片也放到html相同目录下。
在调用该文件时使用如下语句,展示到webview中:

mReadWebView.loadUrl("file:///android_asset/html/show_text.html");

在界面加载完毕后,就可以使用webview.loadUrl方法或webview.evaluateJavascript方法进行加载或执行javascript脚本:

// 调用添加文本方法
// conten为文本内容,可以为html标签的文本也可以是普通文本
webview.loadUrl("javascript:appendText('" + content + "')");
// 显示底部加载的loading图片
webview.evaluateJavascript("loadingLayout.showText();", null)
// 调用底部显示文本
webview.evaluateJavascript("loadingLayout.showImage();", null)

给Html添加文本

给Html添加文本时,一般有标题、内容和分割线,此处在一个方法中直接编辑好插入,代码如下所示:

// 先处理文本
private String appendHtmlText(String title, String htmlText) {
    StringBuilder htmlContent = new StringBuilder();
    // title添加到文本中
    if (!TextUtils.isEmpty(title)) {
        String formatHtmlTitle = "<h1>" + title.trim() + "</h1>";
        htmlContent.append(formatHtmlTitle);
    }
    // 添加HTML文本到TextView中
    htmlContent.append(htmlText);
    if (htmlContent.length() > 0) {
        // 如果已经有文本内容,则添加换行
        htmlContent.append("<br>");
    }
    // 根据上面html中对separator的样式定义,这里可直接在文本后加入一个<div>标签
    htmlContent.append("<div class=\"separator\"></div>");
    return htmlContent.toString();
}

通过上面这段代码可以初步构建出一个Html文本,再通过上面提到的使用webview.loadUrl来加载html中的方法。

String content = appendHtmlText("我是个title","我是个内容");
mReadWebView.post(() -> mReadWebView.loadUrl("javascript:appendText('" + content + "')"));

修改Html中body的背景色

在修改webview背景色的时候通常可以直接设置webview.setbackgroundResource,但也可以通过修改body的背景色来实现。如下:

mReadWebView.evaluateJavascript("document.body.style.backgroundColor = '" + colorStr + "';", null)

此处的colorStr一般为十六进制色值,如:#FFFFFF,#f2f2f2
也可以通过将一个color.xml中的颜色id值转换成十六进制字符串型。

// 颜色转换
private String formatColor(int colorId) {
//        int color = ContextCompat.getColor(this, colorId);
    String hexColor = String.format("#%06X", (0xFFFFFF & colorId));
    return hexColor;
}

// 设置背景色
private void setWebViewBackground(int color) {
    if (mReadWebView != null && color != 0) {
        String colorStr = formatColor(ContextCompat.getColor(this, color));
        mReadWebView.post(() -> mReadWebView.evaluateJavascript("document.body.style.backgroundColor = '" + colorStr + "';", null));
    }
}
// 调用setWebViewBackground(int color)
setWebViewBackground(R.color.color_background);// color_background为color.xml中的色值

修改Html内body中的文本颜色

private void setWebViewTextColor(String colorStr) {
    if (mReadWebView != null) {
        mReadWebView.post(() -> mReadWebView.evaluateJavascript("document.body.style.color = '" + colorStr + "';", null));
    }
}

如果想设置color.xml颜色,可以查看上面设置body背景色中的方法进行转换后设置。

修改webview中内容的字体大小

通过获取websettings设置setDefaultFontSize(int size)。
默认大小为16,介于1和72之间的非负整数。指定范围之外的任何数字都将被固定

// textsize为整数
mReadWebSettings.setDefaultFontSize(mTextSize);

目前项目中也就暂时只用到这几个常见的功能,如果需要更多功能也请留言,我将尽量完善博客,第一次自己写一个html在android中实现这种效果,还有不足之处,请大家指教。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容