Android 11深色模式下BottomNavigationView加载崩溃问题求助
错误日志
Caused by: android.view.InflateException: Binary XML file line #25 in com.example:layout/activity_main: Error inflating class com.google.android.material.bottomnavigation.BottomNavigationView
Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
问题现象
该问题仅出现在运行深色模式的Android 11设备上,Android 11浅色模式下一切正常,新版本Android无此问题。即使将主题改为Theme.AppCompat、Theme.MaterialComponents等,应用仍会崩溃。
相关配置
应用主题配置
基础主题(values/styles.xml)
<style name="AppStyle" parent="Theme.Material3.DayNight.NoActionBar"> <style name="AppStyle.NavActive" parent="Widget.Material3.BottomNavigationView.ActiveIndicator"> <item name="android:color">@color/surface</item> </style>
夜间主题(values-night/styles.xml)
<style name="AppStyle" parent="Theme.Material3.DayNight.NoActionBar">
Gradle依赖版本
implementation 'com.google.android.material:material:1.11.0' implementation 'androidx.appcompat:appcompat:1.6.1'
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.VIBRATE" /> <application android:allowBackup="true" android:enableOnBackInvokedCallback="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:localeConfig="@xml/locales_config" android:supportsRtl="false" android:theme="@style/AppStyle" android:usesCleartextTraffic="true" tools:targetApi="33"> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> <activity android:name=".activities.MainActivity" android:windowSoftInputMode="stateHidden" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Activity布局文件(activity_main.xml)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical"> <FrameLayout android:id="@+id/frame_container" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_nav_menu" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/navbar_background" app:itemActiveIndicatorStyle="@style/AppTheme.NavActive" app:itemIconTint="@color/bottomnav_color" app:itemTextColor="@color/bottomnav_color" app:itemPaddingBottom="25dp" app:itemPaddingTop="10dp" app:menu="@menu/bottom_nav"/> </LinearLayout>
Activity onCreate代码
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); // Restore the state of the currently opened fragment if (savedInstanceState != null) { currentFragment = getSupportFragmentManager().getFragment(savedInstanceState, "currentFragment"); } // Navigation bar init NavigationBarView bottomNav = findViewById(R.id.bottom_nav_menu); // If the current fragment is null, set the default fragment to be loaded if (currentFragment == null) { switch (preferences.s_launchwindow) { case SETTINGS: currentFragment = SettingsFragment.newInstance(); bottomNav.setSelectedItemId(R.id.nav_settings); break; case FEED: currentFragment = FeedFragment.newInstance(); bottomNav.setSelectedItemId(R.id.nav_feed); break; case SOURCES: currentFragment = SourceFragment.newInstance(preferences); bottomNav.setSelectedItemId(R.id.nav_content); break; case DISCOVER: currentFragment = DiscoverFragment.newInstance(preferences); bottomNav.setSelectedItemId(R.id.nav_discover); break; } getSupportFragmentManager().beginTransaction() .replace(R.id.frame_container, currentFragment) .commit(); } bottomNav.setOnItemSelectedListener(item -> { int itemId = item.getItemId(); if (itemId == bottomNav.getSelectedItemId()) { // The selected item is already active, do nothing return true; } preferences = PreferencesManager.loadPreferences(MainActivity.this); if (itemId == R.id.nav_settings) { currentFragment = SettingsFragment.newInstance(); } else if (itemId == R.id.nav_feed) { currentFragment = FeedFragment.newInstance(); } else if (itemId == R.id.nav_content) { currentFragment = SourceFragment.newInstance(preferences); } else if (itemId == R.id.nav_discover) { currentFragment = DiscoverFragment.newInstance(preferences); } return loadFragment(currentFragment); }); bottomNav.findViewById(R.id.nav_feed).setOnLongClickListener(v -> { if (currentFragment instanceof FeedFragment) { FeedFragment feedFragment = (FeedFragment) currentFragment; feedFragment.scrollToTop(); return true; // Event has been consumed } return false; // Event has not been consumed }); }
问题原因与解决方案
核心原因
- Android 11(API 30)深色模式的主题加载逻辑存在兼容性缺陷:Material 3组件在该版本深色模式下,会错误地校验主题继承链——即便使用的
Theme.Material3.DayNight.NoActionBar是AppCompat的后代,系统仍无法正确识别,触发主题校验错误。 - 布局中存在样式引用笔误:
app:itemActiveIndicatorStyle="@style/AppTheme.NavActive"与定义的样式名称AppStyle.NavActive不匹配,导致样式加载失败,进一步触发主题相关异常。
修复步骤
修正样式引用笔误:
将布局中的app:itemActiveIndicatorStyle="@style/AppTheme.NavActive"改为app:itemActiveIndicatorStyle="@style/AppStyle.NavActive",确保样式能正确加载。明确定义夜间主题:
在values-night/styles.xml中创建独立的深色主题,避免与日间主题混淆:<style name="AppStyle.Night" parent="Theme.Material3.Dark.NoActionBar"> <!-- 保留自定义属性 --> </style>然后在基础主题中指定夜间主题:
<!-- values/styles.xml --> <style name="AppStyle" parent="Theme.Material3.DayNight.NoActionBar"> <item name="android:nightTheme">@style/AppStyle.Night</item> <!-- 其他自定义属性 --> </style>降级Material库版本(可选):
Material 1.11.0在Android 11上存在兼容性bug,暂时降级到1.10.0可规避该问题:implementation 'com.google.android.material:material:1.10.0'临时排查EdgeToEdge影响:
注释掉EdgeToEdge.enable(this);,验证是否是该API导致的主题加载冲突,若问题解决,可考虑针对Android 11单独禁用该功能。
内容的提问来源于stack exchange,提问作者Niilo Poutanen

