You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 11深色模式下BottomNavigationView加载崩溃问题求助

深色模式下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
    });
}

问题原因与解决方案

核心原因

  1. Android 11(API 30)深色模式的主题加载逻辑存在兼容性缺陷:Material 3组件在该版本深色模式下,会错误地校验主题继承链——即便使用的Theme.Material3.DayNight.NoActionBar是AppCompat的后代,系统仍无法正确识别,触发主题校验错误。
  2. 布局中存在样式引用笔误:app:itemActiveIndicatorStyle="@style/AppTheme.NavActive"与定义的样式名称AppStyle.NavActive不匹配,导致样式加载失败,进一步触发主题相关异常。

修复步骤

  1. 修正样式引用笔误:
    将布局中的app:itemActiveIndicatorStyle="@style/AppTheme.NavActive"改为app:itemActiveIndicatorStyle="@style/AppStyle.NavActive",确保样式能正确加载。

  2. 明确定义夜间主题:
    在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>
    
  3. 降级Material库版本(可选):
    Material 1.11.0在Android 11上存在兼容性bug,暂时降级到1.10.0可规避该问题:

    implementation 'com.google.android.material:material:1.10.0'
    
  4. 临时排查EdgeToEdge影响:
    注释掉EdgeToEdge.enable(this);,验证是否是该API导致的主题加载冲突,若问题解决,可考虑针对Android 11单独禁用该功能。

内容的提问来源于stack exchange,提问作者Niilo Poutanen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 06:04:53