X5 webView 兼容
当我将代码搬到 x5 webview 的时候,这时候进行滑动,发现无法联动了。
class NestedWebView extends com.tencent.smtt.sdk.WebView implements NestedScrollingChild3
原因分析
这是什么原因呢?
我们点进去 X5 webView 里面的代码,发现 webView 是继承 FrameLayout,而不是继承系统 WebView。
因此我们直接 extends com.tencent.smtt.sdk.WebView,对触摸事件进行拦截,实际上是对 FrameLayout 进行拦截处理,而不是对里面的 WebView 进行拦截处理,那肯定达不到嵌套滑动。
解决方案
我们先来看一下 X5 webView 的 View Tree 结构,因为 X5 webView 代码是混淆的,我们想要通过代码直接看出他的 View Tree,是不太方便的。
于是,我们可以通过代码,将 x5 webView viewTree 结构打印出来
webView = view.findViewById<WebView>(R.id.webview) val childCount = webView.childCount Log.i(TAG, "onViewCreated: webView is $webView, childCount is $childCount") for (i in 0 until childCount) { Log.i(TAG, "x5 webView: childView[$i] is ${webView.getChildAt(i)}") }
运行以上代码,得到以下结果
可以看到 X5 WebView 应该就是在 WebView 的基础之上包了一层 FrameLayout。
那我们对没有办法拿到里面的 TencentWebViewProxy$InnerWebView 对象,其实是有的。他在里面有一个 getView 的方法。
拿到这个对象之后,我们有办法进行拦截处理嘛,像 onTouchEvent, onInterceptTouchEvent 方法?
我们在官方文档中 X5 webview 常见问题 找到这样的描述
3.10 如何重写TBS WebView 的屏幕事件(例如 overScrollBy)
需 setWebViewCallbackClient 和 setWebViewClientExtension 参考代码示例 http://res.imtt.qq.com/tbs/BrowserActivity.zip
通过代码跟踪&调试,我们发现了 WebViewCallBackClient 的接口
当 X5 里面的 webview 进行滑动的时候,会调用相应的方法。那么,我们这时候就可以依样画葫芦,将上面 NestedWebView 的代码逻辑搬下来。
重写 onTouchEvent, onInterceptTouchEvent, computeScroll 这几个关键方法。
这样就实现了嵌套滑动。
具体的代码可以见 nestedwebview
总结
- 借助 NestedScrool 机制,要实现嵌套滑动其实还是蛮简单的,基本按照模板代码魔改一下就好了,要学会举一反三。
- 如果要实现一些自定义的效果,那么我们可以通过 Behavior 来实现,具体的可以参照 自定义 behavior - 完美仿 QQ 浏览器首页,美团商家详情页
参考博客
NestedWebView working properly with ScrollingViewBehavior
源码地址
nestedwebview, 可以帮忙给个 star 哦。