Android平台OPPO设备WebView滚动卡顿、反向滚动问题求助
OPPO设备WebView滚动异常修复方案
该问题由ColorOS系统对WebView的定制化修改导致,其他品牌无同类问题是因为未改动WebView底层触摸、渲染逻辑,可按以下步骤修复:
针对性调整WebView渲染模式
OPPO部分系统版本的WebView硬件加速渲染存在滚动偏移量计算bug,容易触发卡顿、反向滚动异常,初始化时可针对OPPO设备切换软件渲染:// 在setupView方法中加入如下判断 if (Build.MANUFACTURER.equals("OPPO", ignoreCase = true)) { binder.webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null) }禁用滚动越界回弹效果
OPPO系统自带的滚动越界回弹会和WebView本身的滚动逻辑冲突,可直接关闭WebView的越界效果:binder.webView.overScrollMode = View.OVER_SCROLL_NEVER优化WebView基础配置
现有配置基础上补充以下设置,可减少滚动冲突概率:with(binder.webView.settings) { // 原有配置保留,新增以下项 setSupportZoom(false) displayZoomControls = false loadWithOverviewMode = true allowContentAccess = true }处理手势导航事件冲突
若开启了系统手势导航,可自定义WebView的触摸监听,过滤不符合滑动方向逻辑的异常事件:var downX = 0f var downY = 0f binder.webView.setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { downX = event.x downY = event.y v.parent.requestDisallowInterceptTouchEvent(true) } MotionEvent.ACTION_MOVE -> { val offsetX = abs(event.x - downX) val offsetY = abs(event.y - downY) v.parent.requestDisallowInterceptTouchEvent(offsetY > offsetX) } } false }
修改后的完整代码示例:
class WebViewActivity : AppCompatActivity() { lateinit var binder: ActivityWebviewBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binder = DataBindingUtil.setContentView(this, R.layout.activity_webview) setupView() } private fun setupView() { with(binder.webView.settings) { databaseEnabled = true javaScriptEnabled = true domStorageEnabled = true builtInZoomControls = true useWideViewPort = true cacheMode = WebSettings.LOAD_NO_CACHE // 新增配置 setSupportZoom(false) displayZoomControls = false loadWithOverviewMode = true allowContentAccess = true } // 针对OPPO设备适配 if (Build.MANUFACTURER.equals("OPPO", ignoreCase = true)) { binder.webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null) } binder.webView.overScrollMode = View.OVER_SCROLL_NEVER // 触摸冲突处理 var downX = 0f var downY = 0f binder.webView.setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { downX = event.x downY = event.y v.parent.requestDisallowInterceptTouchEvent(true) } MotionEvent.ACTION_MOVE -> { val offsetX = abs(event.x - downX) val offsetY = abs(event.y - downY) v.parent.requestDisallowInterceptTouchEvent(offsetY > offsetX) } } false } binder.webView.webViewClient = BrowserClient() binder.webView.webChromeClient = WebChromeClient() binder.webView.loadUrl("webview_url") } private class BrowserClient : WebViewClient() { override fun shouldOverrideUrlLoading( view: WebView?, request: WebResourceRequest? ): Boolean { return super.shouldOverrideUrlLoading(view, request) } } override fun onBackPressed() { if (binder.webView.canGoBack()) { binder.webView.goBack() } else { super.onBackPressed() } } }
内容的提问来源于stack exchange,提问作者VIKAS SHARMA
相关产品推荐
相关产品推荐

