Android edge-to-edge模式下软键盘弹出时WebView滚动失效修复
问题描述
我们开发的应用采用edge-to-edge模式展示内容,部分核心功能依赖WebView实现。当WebView中弹出软键盘时,页面滚动功能异常,不关闭软键盘就无法滚动查看页面底部内容。
我们搭建了配置完全一致的最简Demo应用,可稳定复现相同问题,需要在必须满足edge-to-edge内容展示要求的前提下,修复WebView的滚动异常问题。
复现代码
Activity代码
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 开启以下edge-to-edge配置后WebView滚动异常 WindowCompat.setDecorFitsSystemWindows(window, false) window.setStatusBarColor(Color.TRANSPARENT); window.setNavigationBarColor(Color.TRANSPARENT); binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) ViewCompat.setOnApplyWindowInsetsListener(binding.toolbar) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) // 给顶部栏添加状态栏高度的上边距 val mlpHeader = view.getLayoutParams() if (mlpHeader is ViewGroup.MarginLayoutParams){ mlpHeader.topMargin = insets.top; } // 消费Insets,不再向下传递 WindowInsetsCompat.CONSUMED } setSupportActionBar(binding.toolbar) binding.webview.loadUrl("https://www.google.com") }
Layout布局代码
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/Theme.MyApplication.AppBarOverlay"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/Theme.MyApplication.PopupOverlay" /> </com.google.android.material.appbar.AppBarLayout> <WebView android:id="@+id/webview" android:layout_marginTop="?attr/actionBarSize" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Manifest配置
<activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.MyApplication.NoActionBar" android:windowSoftInputMode="adjustResize" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
现象对比
- 开启edge-to-edge显示:软键盘弹出后WebView滚动功能异常,无法查看底部内容

- 关闭edge-to-edge显示:软键盘弹出后滚动功能正常

修复方案
问题根源是开启setDecorFitsSystemWindows(false)后,系统不再自动为根布局适配软键盘弹出的Insets,原有代码仅给Toolbar处理了顶部状态栏的Insets,既阻断了Insets向下传递,也没有给WebView处理软键盘、底部导航栏的Insets,导致WebView实际高度没有随软键盘弹出收缩,底部区域被软键盘盖住,自然无法滚动到被遮挡部分。
按以下两步修改即可:
注意:该适配方案要求androidx.core版本不低于1.5.0,才能正确识别软键盘Insets类型
- 调整布局结构,去掉WebView硬编码的顶部margin,使用CoordinatorLayout自带的行为属性适配AppBarLayout高度,避免布局重叠:
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/Theme.MyApplication.AppBarOverlay"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/Theme.MyApplication.PopupOverlay" /> </com.google.android.material.appbar.AppBarLayout> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </androidx.coordinatorlayout.widget.CoordinatorLayout> - 修正Insets传递逻辑,单独给WebView添加系统栏+软键盘的Insets适配:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) window.setStatusBarColor(Color.TRANSPARENT) window.setNavigationBarColor(Color.TRANSPARENT) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // 处理Toolbar的顶部状态栏Insets ViewCompat.setOnApplyWindowInsetsListener(binding.toolbar) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) val mlpHeader = view.layoutParams if (mlpHeader is ViewGroup.MarginLayoutParams){ mlpHeader.topMargin = insets.top } // 不要直接消费全部Insets,将剩余Insets传递给子View windowInsets } // 处理WebView的底部Insets(包含导航栏、软键盘高度) ViewCompat.setOnApplyWindowInsetsListener(binding.webview) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.ime()) // 给WebView设置对应高度的底部padding,避免内容被遮挡 view.setPadding(0, 0, 0, insets.bottom) WindowInsetsCompat.CONSUMED } setSupportActionBar(binding.toolbar) binding.webview.loadUrl("https://www.google.com") }
修改后既可以保留edge-to-edge的全屏显示效果,软键盘弹出时WebView也会自动收缩高度,滚动功能完全正常。
内容的提问来源于stack exchange,提问作者DRBF
相关产品推荐
相关产品推荐

