需求背景:

使用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. 2020年在项目中使用MVVM正确姿势,你用对了吗?

    最近看到了几篇与 Jetpack MVVM 有关到文章,使我不禁也想淌一下这场混水.我是在 2017 年下半年接触的 Jetpack 的那套开发工具,并且后来一直将其作为开发的主要框架.在这段时间的使 ...

  2. windows.h头文件中改变光标位置的函数——SetConsoleCursorPosition

    COORD 具体为 typedef struct COORD{ short X; short Y; } COORD,*PCOORD;     可以用来记录坐标. #include <iostre ...

  3. NLP任务梳理总结

    NLP任务 前处理任务 前处理任务的结果可作为下游任务输入的额外特征. POSTa(词性标注) 往模型中输入句子,对每一个token进行词性的识别. 识别出的词性可以用于下游任务. Word Segm ...

  4. 趣谈多线程(Python版)

    温馨提示:本文篇幅较长,建议读者耐心阅读,本文中的代码经过笔者精心构思,可以复制过去运行一下,观察输出结果,所有代码在python3.5.0中测试通过. 文章目录 What is 多线程? Why w ...

  5. UI设计学习总结

    UI设计学习总结 平面设计基础 平面构成 三大构成:点线面 重复构成 相同,有规律的重复 近似构成 形状,大小,色彩,肌理相似 渐变构成 色彩逐渐变化 发射构成 通过一点向四周扩散犹如绽放的花朵 密集 ...

  6. abstract关键字的说法

    含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象.含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必 ...

  7. 【Flutter 1-2】在 Windows 10下安装Flutter+Dart+Android Studio 配置Flutter开发环境

    在 Windows 10下安装Flutter+Dart+Android Studio 配置Flutter开发环境 文章首发地址 配置环境变量 由于部分网站被墙的原因,我们需要先配置Flutter国内镜 ...

  8. Redis学习笔记(二)——Keys通用操作

    1.查询所有key: keys * 2.*通用符(代表0或多),查询所有以n(*)开头的key: keys n* 3.?通用符(代表1个字符): key n? 4.del删除key [key1 key ...

  9. 关于数据源为授权车辆、企业车辆的判断(限foton)

    int mode = carInfoService.getCompanyCarMode(companyId); public int getCompanyCarMode(Long companyId) ...

  10. Map 和 Json 互转

    Json 转 Map<String,String> String query = "{tableName:\"iov_biz_car_info\",selec ...