需求背景:

使用CoordinatorLayout+viewpager+tablayout+webview实现首页折叠效果。

使用问题:

在使用过程中首页的页面为原生/h5混合页,在原生页面正常,嵌套h5页面头部CollapsingToolbarLayout无法滚动,开始的解决方式是在webview上面嵌套NestedScrollView。

项目上线后发现了新的问题,h5关于滑动的js都无法执行。

原因分析:

引用Coordinator layout 和 WebView中的话是:

如果将webview放在NestedScrollView中,height是wrap_contents,并且webview扩展为页面的大小。 因此无法垂直滚动。 滚动是在NestedScrollView而不是webview本身发生的。
所以页面中没有js的结果会看到任何滚动事件,所以它不知道你已经滚动到页面的末尾加载更多的内容。
硬件层也由GL纹理支持,并且它们具有最大尺寸(这是最小的屏幕尺寸,尽管通常不会大得多)。 如果视图变得大于最大纹理大小,那么它将不能与硬件层一起使用。 这适用于任何视图,而不仅仅是webview。

建议:

不要将webview放在NestedScrollView中。 不要在wrap_contents模式下使用webview。 让webview滚动网页本身。

解决方案:

自定义webview,由它实现NestedScrollingChild。

package com.ingtube.common.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent; import androidx.core.view.MotionEventCompat;
import androidx.core.view.NestedScrollingChild;
import androidx.core.view.NestedScrollingChildHelper;
import androidx.core.view.ViewCompat; public class NestedScrollWebView extends ScrollWebView implements NestedScrollingChild {
public NestedScrollWebView(@NotNull Context context) {
super(context);
init();
} public NestedScrollWebView(@NotNull Context context, @NotNull AttributeSet attrs) {
super(context, attrs);
init();
} public NestedScrollWebView(@NotNull Context context, @NotNull AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private int mLastMotionY; private final int[] mScrollOffset = new int[2];
private final int[] mScrollConsumed = new int[2]; private int mNestedYOffset; private NestedScrollingChildHelper mChildHelper; private void init() {
mChildHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
} @Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = false; MotionEvent trackedEvent = MotionEvent.obtain(event); final int action = MotionEventCompat.getActionMasked(event); if (action == MotionEvent.ACTION_DOWN) {
mNestedYOffset = 0;
} int y = (int) event.getY(); event.offsetLocation(0, mNestedYOffset); switch (action) {
case MotionEvent.ACTION_DOWN:
mLastMotionY = y;
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
result = super.onTouchEvent(event);
break;
case MotionEvent.ACTION_MOVE:
int deltaY = mLastMotionY - y; if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
deltaY -= mScrollConsumed[1];
trackedEvent.offsetLocation(0, mScrollOffset[1]);
mNestedYOffset += mScrollOffset[1];
} int oldY = getScrollY();
mLastMotionY = y - mScrollOffset[1];
int newScrollY = Math.max(0, oldY + deltaY);
deltaY -= newScrollY - oldY;
if (dispatchNestedScroll(0, newScrollY - deltaY, 0, deltaY, mScrollOffset)) {
mLastMotionY -= mScrollOffset[1];
trackedEvent.offsetLocation(0, mScrollOffset[1]);
mNestedYOffset += mScrollOffset[1];
}
if(mScrollConsumed[1]==0 && mScrollOffset[1]==0) {
trackedEvent.recycle();
result = super.onTouchEvent(trackedEvent);
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
stopNestedScroll();
result = super.onTouchEvent(event);
break;
}
return result;
} // NestedScrollingChild @Override
public void setNestedScrollingEnabled(boolean enabled) {
mChildHelper.setNestedScrollingEnabled(enabled);
} @Override
public boolean isNestedScrollingEnabled() {
return mChildHelper.isNestedScrollingEnabled();
} @Override
public boolean startNestedScroll(int axes) {
return mChildHelper.startNestedScroll(axes);
} @Override
public void stopNestedScroll() {
mChildHelper.stopNestedScroll();
} @Override
public boolean hasNestedScrollingParent() {
return mChildHelper.hasNestedScrollingParent();
} @Override
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
} @Override
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
} @Override
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
} @Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
} }

参考链接:

解决coordinatorlayout嵌套webView遇到的问题

问题记录-CoordinatorLayout+WebView使用遇到的问题的更多相关文章

  1. WebView使用详解(二)——WebViewClient与常用事件监听

      登录|注册     关闭 启舰 当乌龟有了梦想……       目录视图 摘要视图 订阅 异步赠书:Kotlin领衔10本好书      免费直播:AI时代,机器学习如何入门?      程序员8 ...

  2. 《Android编程权威指南》PhotoGallery应用梳理

    PhotoGalley是<Android编程权威指南>书中另外一个重要的应用.       

  3. Android WebView默认GONE出现的问题记录

    前段时间重构一批相似度80%以上的项目[真搞不懂前人们是怎么忍受十几个类似的应用一直CVU的,冗余代码和资源达到40%以上] 其中需要抽出一个公共的带WebView的Activity基类,由于脑残测试 ...

  4. appium+python自动化42-微信公众号 (可能以后会遇到也遇到切换不了webview的问题 记录再此 还没试)

    前言 本篇介绍如何在微信公众号上自动化测试,以操作我的个人公众号:yoyoketang为例,没关注的,先微信关注了,再跟着操作 环境准备:python 3.6appium 1.7以上版本微信6.6.6 ...

  5. 切换了webview 定位不了的解决方法 (还没有试,记录在此)

    # 切换到 webview time.sleep(2) print(driver.contexts) driver.switch_to.context('WEBVIEW_com.tencent.mm: ...

  6. 小程序web-view wx.miniProgram.postMessage 坑记录

    web-view吧,其实微信官方应该是非常不支持在小程序上嵌套web的,它希望你直接用小程序上的代码,而放弃web的实现,当然,也是为了防止用小程序去嵌套别的广告页面.所以官方对web-view的操作 ...

  7. Appium Hybrid混合应用测试——Native切换WebView , 切换不了WebView (没有试过,先记录在此)

    Appium Hybrid混合应用测试过程中,经常需要在Native和WebView之间进行切换: 1.切换至WEBVIEW操作: for cons in driver.contexts: if co ...

  8. Android。WebView加载UR请求使用Cookie储存User_Id记录用户是否登陆过

    1.WebView初始化的时候用倒如下代码: if (Build.VERSION.SDK_INT >= 21) { CookieManager.getInstance().setAcceptTh ...

  9. Android webview 问题记录

    1. Android 7.1真机安装调试apk时报错,解析安装包失败 原因:sdk版本不支持7.1版本,需要调整minSdkVersion等参数,支持低版本 解决方法: android { compi ...

随机推荐

  1. spring 源码构建

    参照这里(按照下面链接一路绿灯) https://blog.csdn.net/chengqiuming/article/details/102331033 1.安装配置gradle环境 1).  配置 ...

  2. java字符流与字节流的区别是什么

    java中字符流与字节流的区别: 1.字节流操作的基本单元为字节:字符流操作的基本单元为Unicode码元. 2.字节流默认不使用缓冲区:字符流使用缓冲区. 3.字节流通常用于处理二进制数据,实际上它 ...

  3. vmware 安装tools

    kali linux 更换成国内源后 安装tools命令 apt install open-vm-tools-desktop fuse -y 需重启  reboot

  4. 好用的C语言编程软件!工具都没有,怎么用技术改变世界呢!

    好用的C语言编程软件 1.VS(Visual Studio)   VS(Visual Studio) VS是目前最流行的windows平台应用程序的集成开发环境,由于大部分同学使用的都是Windows ...

  5. Harbor 安装教程

    Harbor 安装教程 一. CentOS设置 1. 更换阿里源 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com ...

  6. Luogu-2480 古代猪文

    我们首先来概括一下题意,其实就是给定 \(n,g\),求: \[g^{\sum_{k\nmid n} C_n^{\frac{n}{k}}}\operatorname{mod} 999911659 \] ...

  7. JS变量作用域与解构赋值

    用var变量是有作用域的 变量在函数内部声明时,那么该变量只属于整个函数体,函数外不可调用 当两个不同的函数里,使用了用一个相同的变量名,二者不互相影响,相互独立 遇到嵌套函数时,外部函数不可调用内部 ...

  8. 对于72种常用css3的使用经验

    对于72种常用css3的使用经验 保存网站源码 目的 保证有足够的css和js文件源码 拿到当前网页的整体布局 本地化 创建web项目 将web项目创建出来 在项目中创建一个文件夹 将所有的js和cs ...

  9. servlet post response.sendRedirect 乱码

    response.sendRedircet一般用于传递字符串参数 常会出现乱码: 情景1: post表单提交,跳转后的servlet,通过getParameter(name)进行解码,获取的中文乱码 ...

  10. 老板,来几道web玩玩

    好久没做web了,没想到还能自己做出来555 [MRCTF2020]Ez_bypass 签到题8 给了源码,一个md5强类型比较,然后post传参,弱类型判断,直接1234567a绕过了 I put ...