解决BottomSheetDialog搭配EditText时键盘弹出动画中显示Activity背景的问题
嘿,我完全懂你遇到的这个糟心问题——键盘弹起的动画过程中,Activity的粉色背景露出来确实很破坏体验,像Instagram、YouTube这些APP都处理得丝滑无痕,咱们也能搞定它!
先唠唠问题根源:当你点击EditText弹出键盘时,因为设置了adjustResize,系统会调整布局让BottomSheet向上移动,但动画过程中,BottomSheetDialog的窗口并没有完全覆盖住Activity的底部区域,所以Activity的背景就从缝隙里透出来了。
下面给你几个实用的解决方案,你可以根据自己的情况选:
方案一:修改Dialog样式,设置窗口背景色(最简单)
直接在你的ModalBottomSheetDialog样式里加一行,把Dialog的窗口背景改成和BottomSheet一致的黑色,这样即使有间隙,显示的也是黑色,就看不到粉色了。
修改themes.xml里的ModalBottomSheetDialog:
<style name="ModalBottomSheetDialog" parent="ThemeOverlay.Material3.BottomSheetDialog"> <item name="bottomSheetStyle">@style/ModalBottomSheet</item> <item name="colorSurface">#000000</item> <item name="android:windowSoftInputMode">adjustResize</item> <!-- 新增这一行,设置窗口背景为黑色 --> <item name="android:windowBackground">@android:color/black</item> </style>
方案二:给BottomSheet容器添加全屏背景View
如果方案一没生效,咱们可以手动在BottomSheet的容器最底层加一个全屏的黑色View,彻底盖住Activity的背景。
修改BottomSheetCommentSection.kt里的onCreateDialog方法:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val bottomSheetDialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog bottomSheetDialog.setOnShowListener { val containerLayout = dialog?.findViewById( com.google.android.material.R.id.container ) as? FrameLayout // 先添加一个全屏的黑色背景View,放在最底层 val fullScreenBackground = View(requireContext()) fullScreenBackground.setBackgroundColor(Color.BLACK) val bgLayoutParams = FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT ) containerLayout?.addView(fullScreenBackground, 0) // 索引0确保在最下面 // 你原来的添加EditText代码保持不变 val layoutEdittextNewCommentBinding = LayoutEdittextNewCommentBinding.inflate( LayoutInflater.from(requireContext()) ) val layoutParams = FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM ) containerLayout?.addView( layoutEdittextNewCommentBinding.root, layoutParams ) // 原来的padding设置代码也不变 layoutEdittextNewCommentBinding.root.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { layoutEdittextNewCommentBinding.root.viewTreeObserver.removeOnGlobalLayoutListener( this ) bottomSheetLayoutBinding.root.setPadding( 0, 0, 0, layoutEdittextNewCommentBinding.root.measuredHeight ) } }) } return bottomSheetDialog }
方案三:让BottomSheet占据全屏高度
另一种思路是让BottomSheet本身就占满整个屏幕,内容放在滚动容器里,这样键盘弹出时只是内容上移,BottomSheet的高度不会变,自然不会露出背景。
修改bottom_sheet_layout.xml:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000000"> <!-- 给CoordinatorLayout设置黑色背景 --> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <View android:id="@+id/viewTop" android:layout_width="match_parent" android:layout_height="40dp" android:background="#FF0000" /> <View android:id="@+id/view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/viewTop" android:background="#000000" /> </RelativeLayout> </androidx.core.widget.NestedScrollView> </androidx.coordinatorlayout.widget.CoordinatorLayout>
建议你先试试方案一,改动最小,大概率能解决问题。如果还是有问题,再试方案二或三,应该就能达到像Instagram那样的丝滑效果啦!
备注:内容来源于stack exchange,提问作者Miha M

