Android加载BottomSheetDialog时HomeFragment消失问题咨询
问题根因
- 全局主题配置错误:你在
Theme.MyApp中设置了<item name="android:background">@color/black</item>,该属性会被继承到所有派生自该主题的窗口,包括BottomSheetDialog的窗口,导致Dialog弹出时整个窗口背景被黑色覆盖,看起来就像下层的HomeFragment消失了。 - 布局加载逻辑错误:初始化BottomSheetDialog布局时,
findViewById(R.id.bottom_sheet)在Activity的布局中不存在(该id属于bottom_sheet_layout内部控件),传入不存在的root会导致布局参数丢失,进一步加剧显示异常。 - 弹出时机错误:在Activity的
onCreate中直接弹出Dialog,此时FragmentContainerView自动加载HomeFragment的事务还未完全执行完成,Dialog的窗口生命周期触发会干扰Fragment的绘制流程。
解决方案
方案一:直接修复原有实现
不需要调整Dialog的所属位置,修改现有代码即可解决问题:
- 修改
themes.xml,移除全局的android:background配置,不要把全局背景放在Application主题上,需要给Activity设背景直接在activity_main.xml的根ConstraintLayout中加android:background="@color/black"即可:
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <!-- Primary brand color. --> <item name="colorPrimary">@color/red_700</item> <item name="colorPrimaryVariant">@color/red_900</item> <!-- 移除这行<item name="android:background">@color/black</item> --> <item name="android:textColor">@color/white</item> <!-- Status bar color. --> <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> <!-- Customize your theme here. --> <item name="android:listDivider">@drawable/divider</item> </style>
- 修改
BottomSheetTheme的父类为MaterialComponents版本,和应用主题统一避免兼容问题:
<style name="BottomSheetTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog"> <item name="bottomSheetStyle">@style/BottomSheetStyle</item> <item name="android:backgroundDimEnabled">true</item> <item name="android:backgroundDimAmount">0.5</item> </style>
- 修改MainActivity中Dialog的初始化和弹出逻辑:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); toolbar.setSubtitle("Workout"); toolbar.setNavigationOnClickListener(v -> { getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainerView, new HomeFragment()).commit(); toolbar.setSubtitle("Workout"); }); bottomSheetDialog = new BottomSheetDialog(this, R.style.BottomSheetTheme); // 正确加载布局 View sheetView = LayoutInflater.from(this).inflate(R.layout.bottom_sheet_layout, null, false); bottomSheetDialog.setContentView(sheetView); // 等Activity布局绘制完成再弹出Dialog,避免干扰Fragment加载 findViewById(android.R.id.content).post(() -> { bottomSheetDialog.show(); }); }
方案二:将Dialog迁移到HomeFragment中实现
按照你的需求把Dialog放到子Fragment中加载,步骤如下:
- 删除MainActivity中所有和BottomSheetDialog相关的初始化、弹出代码。
- 在HomeFragment的
onViewCreated方法中初始化并弹出Dialog:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(requireContext(), R.style.BottomSheetTheme); View sheetView = LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_layout, null, false); bottomSheetDialog.setContentView(sheetView); // 等Fragment布局绘制完成再弹出 view.post(() -> { bottomSheetDialog.show(); }); }
内容的提问来源于stack exchange,提问作者Bryan Sanchez
相关产品推荐
相关产品推荐

