需求:管理端有个富文本可以添加一个阅读须知,通过接口将富文本生成的Html返回给Android端,要求展示正确展示富文本内容,并且如果内容较多时,用户需要看完所有内容(滑动到底部)才能确认进入下一步。

简单来说需要实现加载Html片段,并且根据内容多少判断是否需要滑动到底部和是否滑动到底部了。下面封装一个自定义的WebView,实现此需求:

package com.zhn.learn_android;import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebView;import java.util.concurrent.TimeUnit;import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;/*** @author : zhn* @date : 2022/11/1 14:04* description :滑动监听WebView*/
public class ScrollListenerWebView extends WebView {//webView的高度,dppublic int viewHeight = 0;//web内容高度,dppublic int contentHeight = 0;public ScrollListenerWebView(Context context) {super(getFixedContext(context));}public ScrollListenerWebView(Context context, AttributeSet attrs) {super(getFixedContext(context), attrs);}public ScrollListenerWebView(Context context, AttributeSet attrs, int defStyleAttr) {super(getFixedContext(context), attrs, defStyleAttr);}@TargetApi(Build.VERSION_CODES.LOLLIPOP)public ScrollListenerWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);}/*** 解决Android 5.0~5.1 WebView兼容问题* @param context ctx* @return ctx*/private static Context getFixedContext(Context context) {// Android Lollipop 5.0 & 5.1if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23) {return context.createConfigurationContext(new Configuration());}return context;}/*** 添加获取** @param activity activity*/public void addWebHeightSupport(Activity activity, ScrollWebListener listener) {this.mListener = listener;addWebHeightSupport(activity, this, "app");}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);viewHeight = px2dip(getContext(), getMeasuredHeight());Log.e("onMeasure","   viewHeight= "+viewHeight);}@JavascriptInterfacepublic void contentHeight(int webContentHeight) {contentHeight = webContentHeight;if (mListener == null || contentHeight <= 0) {return;}Log.e("","contentHeight="+contentHeight);//如果html高度小于控件高度,那么说明一屏可以展示下if (contentHeight < viewHeight) {mListener.noScroll();} else {mListener.needScroll();}}@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);if (mListener == null) {return;}// 当前webview的高度float webNow = viewHeight + px2dip(getContext(),getScrollY());//判断是否抵达底部if (webNow >= contentHeight - 10) {mListener.scrollBottom();}}/*** 添加内容高度支持** @param activity        activity* @param jsInterface     js接口* @param jsInterfaceName js接口名称*/@SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface", "JavascriptInterface"})private void addWebHeightSupport(Activity activity, Object jsInterface, String jsInterfaceName) {//js支持getSettings().setJavaScriptEnabled(true);//添加JS交互方法this.addJavascriptInterface(jsInterface, jsInterfaceName);//监听加载进度setWebChromeClient(new WebChromeClient() {@Overridepublic void onProgressChanged(WebView view, int newProgress) {super.onProgressChanged(view, newProgress);addWebHeightSupport(newProgress);}});}/*** 添加内容高度预览支持** @param newProgress 加载进度*/private void addWebHeightSupport(int newProgress) {if (newProgress == 100) {Observable.timer(200L, TimeUnit.MILLISECONDS).observeOn(AndroidSchedulers.mainThread()).safeSubscribe(new Observer<Long>() {@Overridepublic void onSubscribe(Disposable d) {}@Overridepublic void onNext(Long aLong) {loadUrl("javascript:(function(){" +"var result = document.body.offsetHeight; " +"window.app.contentHeight(result);" +"})()");}@Overridepublic void onError(Throwable e) {}@Overridepublic void onComplete() {}});}}private ScrollWebListener mListener;public interface ScrollWebListener {void noScroll();void needScroll();void scrollBottom();}/*** 获取Html前缀** @return*/public String getHtmlPrefixStr() {return "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no'>" +"<style>" +"*{margin:0 !important;}" +"img{width:100% !important; height:auto !important; margin-top:10px !important;margin-bottom:10px !important; border-radius:4px;}" +"div{font-size:14px !important; color: #3A3D4B !important; font-family: PingFangSC;}" +"body{padding: 20px 16px 20px 20px;}" +"</style>" +"</head><body><div>";}/*** 获取Html后缀** @return*/public String getHtmlSuffixStr() {return "</div></body></html>";}/*** 加载Html片段** @param htmlPart html片段*/public void loadHtmlPart(String htmlPart) {loadDataWithBaseURL(null, getHtmlPrefixStr() + htmlPart + getHtmlSuffixStr(),"text/html", "utf-8", null);}public int px2dip(Context context, float pxValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (pxValue / scale + 0.5f);}}

使用:

package com.zhn.learn_androidimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Buttonclass TestActivity : AppCompatActivity() {private var mWebView:ScrollListenerWebView?=nullprivate var btnConfirm:Button?=nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_test)mWebView=findViewById(R.id.web_view)btnConfirm=findViewById(R.id.btn_confirm)mWebView!!.addWebHeightSupport(this,object : ScrollListenerWebView.ScrollWebListener{override fun noScroll() {Log.e("-TestActivity--","不需要滑动")btnConfirm!!.isEnabled=true}override fun needScroll() {Log.e("-TestActivity--","需要滑动")btnConfirm!!.isEnabled=false}override fun scrollBottom() {Log.e("-TestActivity--","滑动到底部了")btnConfirm!!.isEnabled=true}})}fun loadWithHtmlPart(view:View){var htmlPart="<p>阿神经asx酰胺北ahsx京</p>" +"<img src=\"https://img2.baidu.com/it/u=1245013499,1883492144&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500\">" +"<p>市西安ajsbhx不熟悉asbx啊</p>" +"<img src=\"https://img2.baidu.com/it/u=1245013499,1883492144&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500\">"mWebView!!.loadHtmlPart(htmlPart)}}

效果:

device-2022-11-06-144942

总结:

1、给Html片段添加Html头和尾

2、重写onMeasure方法获取WebView控件的高度

3、通过Js交互获取html中body的高度,与WebView高度对比判断是否需要滑动

4、监听WebView的onScrollChanged方法,判断是否滑动到底部了

WebView加载Html片段监听滑动到底部相关推荐

  1. Android WebView加载完成的监听

    在项目里有时会需要监听WebView加载完成的状态,可能有人会使用WebViewClient里onPageFinished这个方法来监听,可是这个官方的方法到现在还是不稳定,有些能监听到,有些则不能. ...

  2. ajax下拉 加载 下一页,jQuery滑动到底部加载下一页数据的实例代码

    page_num =page_num+1 ; //页码自动增加,保证下次调用时为新的一页. $.ajax({ type: "get", url: rent_url, data: ' ...

  3. vue图片懒加载插件vue-lazyload监听加载失败事件的解决方案

     对于vue项目而言,图片懒加载是一个常见的图片加载方案,可以优化用户体验,而vue-lazyload则是一个广泛使用的插件.  对于某些业务场景,我们需要监听图片加载失败事件,而后进行相应的处理,然 ...

  4. angular监听图片加载完成_angular监听dom渲染完成,判断ng-repeat循环完成

    一.前言 最近做了一个图片懒加载的小插件,功能需要dom渲染完成后,好获取那些需要懒加载的dom元素.那么问题来了,如果只是感知静态的dom用ready,onload都可以,但项目用的angular, ...

  5. WebView加载失败或网络异常时,替换WebView的错误界面;

    WebView在加载失败时会显示一个失败原因的界面,各个手机显示的界面还都不一样,部分手机还会把Url显示出来:我们要做的就是统一加载失败的界面: 大概思路:在WebView这个控件上面再覆盖一个Vi ...

  6. Android WebView加载网页,图片等元素宽度大小不兼容手机屏幕的宽度

    无论是Android手机还是iOS手机,使用WebView加载一些没有专门为手机屏幕做适配的网页的时候,就会出现网页中的图片等标签元素的宽度大小和手机屏幕的宽度不一致的情况,如下图 之所以会出现上面的 ...

  7. webview加载超长图

    前言:android开发要经常和图片打交道.关于如何缓存,如何加载网上有很多框架.但是当我加载640*6149的长图时,实现起来效果并不理想,我用的是fresco加载.由于OpenGL渲染系统限制,A ...

  8. Flutter webView加载html富文本

    WebView 加载 Html 字符串 1.添加依赖 在项目的 pubspec.yaml 文件中添加 webview_flutter 插件的依赖: dependencies: webview_flut ...

  9. Webview加载pdf遇到的一些坑及解决方法

    大厂技术  高级前端  Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 问题来源 问题一切的来源还是得从那天说起... 有一天产品小王拿着电脑兴致勃勃的来到我的工位 ...

最新文章

  1. incompatible with sql_mode=only_full_group_by
  2. Agile Manifesto and principle
  3. C/C++语言开源库
  4. sublime突然中文乱码
  5. 机器思维。一些让我眼前一亮的算法。
  6. SQL Server常用约束表达式实例
  7. 信息学奥赛一本通(1124:矩阵加法)
  8. 使用.NET Core 3.1构建Windows Worker服务以删除文件夹中的旧文件
  9. TokenInsight:反映区块链行业整体表现的TI指数较昨日同期上涨6.21%
  10. matlab字体设置
  11. 解决Mac Chrome打开HTTPS证书错误问题
  12. Unite'17 Shanghai再一次问候
  13. 计算机学不学p图的,五分钟学会P图!只需要电脑自带的看图软件!无需专业的PS软件!...
  14. 用计算机绘制工作表,实用计算机机械图样绘制技法
  15. Waiter,Servant, Attendant的区别
  16. hive中的date函数
  17. Docker 学习之 Docker 容器数据卷
  18. Word模板生成C#源码
  19. 求1-1000以内的回文素数。回文素数指的是这个数既是回文数又是素数。
  20. 班尼机器人维修方法_工业机器人常见故障和修理方法

热门文章

  1. python可视化数据分析-Python数据分析与可视化从入门到精通
  2. 第二证券|家用储能设备出口暴增,储能概念发力走高,派能科技等大涨
  3. 欧州专线的使用安全吗主要优势是什么
  4. 工具使用——使用华为手机作为电脑的拓展屏
  5. 色彩的基本原理——正色和负色
  6. 大数据分析的下一代架构--IOTA架构[上]
  7. Marlin架构解析
  8. 常用芯片数据手册——MP2315S/3A、24V、500kHz、高效率同步降压变换器(MPS)
  9. 不会吧,你开发直播卖货软件源码时,不用PHP写后台?
  10. 【微信技术-微信小程序】------- 骨架屏(加载流)配置(skeleton-config)及属性详解 (第三篇)