需求背景:

使用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. OpenStack最新版本--Victoria发布亮点与初体验

    前言 `OpenStack`是一个云操作系统,可控制整个数据中心内的大型计算,存储和网络资源池,所有资源均通过具有通用身份验证机制的`API`进行管理和配置. 还提供了一个仪表板,可让管理员进行控制, ...

  2. 加密sqlite3数据库文件

    目录 EncryptSqlite3 实现原理 使用方法 不足之处 GitHub地址 EncryptSqlite3 加密sqlite3数据库,产生的数据库文件别人打不开. 实现原理 在写入文件前对每个字 ...

  3. spring boot: 用thymeleaf嵌套循环展示多层数据(spring boot 2.3.2)

    一,什么情况下会用到嵌套循环? 当我们展示多个分类时,每个分类下又展示出推荐的前几个商品,   这时我们需要用到嵌套循环 看一个例子: 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https:/ ...

  4. spring boot:构建多模块项目(spring boot 2.3.1)

    一,为什么要使用多模块? 1,结构更清晰,方便管理    如果只是一个小项目当然没有问题,    但如果功能越增越多则管理越来越复杂,    多模块可以使项目中模块间的结构分离   2,把项目划分成多 ...

  5. Linux安装软件时90%的人会遇到这个报错,如何解决?

    提示 Could not get lock /var/lib/dpkg/lock 报错? 有些小伙伴在使用 apt 包管理器更新或安装软件时,可能会遇到过诸如以下的错误提示: E: Could not ...

  6. JS实现鼠标移入水波效果

    前言 最近比较沉迷JS,所以我现在来做个鼠标的交互效果 HTML <div style="border-radius;position:relative;width:800px;hei ...

  7. Android 限制控件多次点击

    有时候多次点击页面会连续弹出多个页面,这时候写一个方法控制一下就OK.  private static long lastClickTime; public synchronized static b ...

  8. D. Kilani and the Game 解析(裸BFS、實作)

    Codeforce 1105 D. Kilani and the Game 解析(裸BFS.實作) 今天我們來看看CF1105D 題目連結 題目 給一個\(n\times m\)的地圖,地圖上有幾種格 ...

  9. B. Psychos in a Line 解析(思維、單調棧)

    Codeforce 319 B. Psychos in a Line 解析(思維.單調棧) 今天我們來看看CF319B 題目連結 題目 給一個數列,如果相鄰兩數,左邊大於右邊,那麼就可以殺死右邊的數字 ...

  10. Cobalt Strike使用的一些技巧

    利用msf模块上线beacon shell 当通过CS的mimikatz或者其他方式获得了目标机器的明文密码或者哈希时,可以利用metasploit的psexec_command模块来上线CS的bea ...