切换ViewPager碎片时BottomSheetDialogFragment被导航栏遮挡
问题描述
我的BottomSheetDialogFragment初始显示正常,悬浮在导航栏上方。
点击继续切换新视图后,BottomSheetDialogFragment会延伸到导航栏后方,底部按钮被遮挡,手动上滑可让其覆盖导航栏。
手动上滑后的显示效果如下:
经排查,问题与com.stripe.android.view.CardFormView相关——移除该视图后显示完全正常,只有当这个视图可见时,底部按钮才会错位。请问如何让底部弹窗在加载新视图时自动重置布局位置,避免被导航栏遮挡?
相关代码
TPCollectPaymentDialog.kt
class TPCollectPaymentDialog() : BottomSheetDialogFragment() { private var _binding: BottomSheetDialogBinding? = null private val binding get() = _binding!! override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NORMAL, R.style.BottomSheetDialog) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = BottomSheetDialogBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.viewPager2.orientation = ViewPager2.ORIENTATION_HORIZONTAL binding.viewPager2.adapter = TPStandardFlowPageAdapter(this) binding.viewPager2.isUserInputEnabled = false } override fun onDestroyView() { super.onDestroyView() _binding = null } }
bottom_sheet_dialog.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.cardview.widget.CardView android:id="@+id/card_view_dialog_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="0dp" android:clipChildren="true" android:padding="0dp" app:cardCornerRadius="16dp" app:cardUseCompatPadding="true"> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager2" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> </androidx.viewpager2.widget.ViewPager2> </androidx.cardview.widget.CardView> </androidx.constraintlayout.widget.ConstraintLayout>
ManualEntryFragment.kt
class ManualEntryFragment : Fragment(), BluetoothReaderListener { private var _binding: CardManualPaymentBinding? = null private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = CardManualPaymentBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.tvErrorMessage.remove() binding.progressBar.remove() binding.btnCancel.show() } override fun onResume() { super.onResume() binding.root.requestLayout() } override fun onDestroyView() { super.onDestroyView() _binding = null } }
manual_card_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="0dp" android:animateLayoutChanges="true" android:gravity="center_horizontal" android:keepScreenOn="true" android:orientation="vertical" android:padding="0dp"> <!-- 为简洁起见移除其他元素 --> <com.stripe.android.view.CardFormView android:id="@+id/card_form_view" style="@style/StripeCardFormView" android:layout_width="match_parent" android:layout_height="wrap_content" /> <ProgressBar android:id="@+id/progressBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:progressTint="@color/colorPrimary" /> <Button android:id="@+id/btnCheckout" android:layout_width="match_parent" android:layout_height="60dp" /> <Button android:id="@+id/btnCancel" android:layout_width="match_parent" android:layout_height="54dp" /> </LinearLayout>
解决方案
针对CardFormView导致BottomSheet布局错位的问题,可尝试以下几种方法:
1. 强制BottomSheet重新计算布局
在ManualEntryFragment的onResume中延迟触发BottomSheet的状态重置,确保CardFormView完成渲染:
override fun onResume() { super.onResume() view?.postDelayed({ val dialog = requireDialog() as BottomSheetDialog val bottomSheetBehavior = BottomSheetBehavior.from(dialog.findViewById(R.id.design_bottom_sheet)) // 先收缩再展开,触发布局重算 bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED }, 100) }
2. 调整BottomSheet窗口适配规则
在TPCollectPaymentDialog的onStart方法中,设置窗口适配系统导航栏,同时锁定BottomSheet的适配行为:
override fun onStart() { super.onStart() val dialog = dialog as BottomSheetDialog val window = dialog.window window?.decorView?.apply { // 让布局稳定适配导航栏 systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION } // 强制BottomSheet适配内容高度 val bottomSheetBehavior = BottomSheetBehavior.from(dialog.findViewById(R.id.design_bottom_sheet)) bottomSheetBehavior.isFitToContents = true bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED }
3. 监听CardFormView布局完成事件
在ManualEntryFragment中监听CardFormView的布局完成事件,完成后立即触发BottomSheet重布局:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // ...其他代码 binding.cardFormView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { binding.cardFormView.viewTreeObserver.removeOnGlobalLayoutListener(this) val dialog = requireDialog() as BottomSheetDialog BottomSheetBehavior.from(dialog.findViewById(R.id.design_bottom_sheet)).apply { requestLayout() state = BottomSheetBehavior.STATE_EXPANDED } } }) }
4. 调整布局适配导航栏
修改manual_card_fragment.xml的根布局,添加导航栏高度的底部内边距,确保按钮不被遮挡:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="0dp" android:animateLayoutChanges="true" android:gravity="center_horizontal" android:keepScreenOn="true" android:orientation="vertical" android:paddingBottom="?android:attr/navigationBarSize" android:padding="0dp">
内容的提问来源于stack exchange,提问作者user-44651
相关产品推荐
相关产品推荐

