在我的应用布局中使用 com.google.android.material.bottomnavigation.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 中使用灯光模式时,一切正常。
这是基本应用程序主题:
<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>
这在主题/夜晚中使用:
<style name="AppStyle" parent="Theme.Material3.DayNight.NoActionBar">
即使我将其更改为 Theme.AppCompat、Theme.MaterialComponents 等,应用程序仍然会崩溃。
为什么会这样?尽管浅色和深色主题相同,但应用程序在深色模式下仍会崩溃。在较新的 Android 版本中,这种情况不会发生。到目前为止,只有深色模式下的 Android 11 存在这些问题。
这些是使用的 gradle 版本:
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
这里的答案:
此组件上的样式要求您的应用程序主题为 Theme.MaterialComponents (或后代)
没用。
<?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>
活动布局:
<?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>
创建活动:
@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
});
检查主题中的所有颜色值是否设置正确。如果某些值(例如 textPrimary 或 colorAccent)设置为不存在的值,则会发生崩溃。
而且崩溃消息非常具有误导性,该问题与 Theme.AppCompat 无关