使用 AndroidX 包含工具栏会使我的应用程序崩溃

Including a toolbar using AndroidX makes my app crashing

您好,我查找了有关使用 AndroidX 的工具栏的早期问题,但没有找到针对我的特定状态的答案,在我的 activity_main.xml 中包含此工具栏时它一直崩溃: 这是我的工具栏 xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.appcompat.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" >
    </androidx.appcompat.widget.Toolbar>

</LinearLayout>

我的MainActivity.java代码:

package com.hfad.bitsandpizzas.ui.activities;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import androidx.appcompat.widget.Toolbar;
import com.hfad.bitsandpizzas.R;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }
}

这是我在 gradle 构建中添加的依赖项:

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.13.1'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

这是我的 Logcat 错误:

原因:java.lang.ClassCastException:android.widget.LinearLayout 无法转换为 androidx.appcompat.widget.Toolbar 在 com.hfad.bitsandpizzas.ui.activities.MainActivity.onCreate

要么你膨胀了错误的视图,要么你的主题已经有了工具栏。

使用默认主题

如果您使用包含操作栏的 Material 设计主题(例如:Theme.MaterialComponents.DayNight.DarkActionBar),则您无需提供 ActionBar/Toolbar,因为它会在那里.

使用默认主题但没有其“工具栏”

如果您想拥有自己的 AppBarLayout/MaterialToolbar(这样您就可以对其进行自定义),那么您需要更改 Activity 的主题(或者如果您在任何地方都这样做,则更改整个应用程序的主题)至 Theme.MaterialComponents.DayNight.NoActionBar

因此,无论哪种情况,在您定义应用程序主题的 themes.xml 中...

<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.NoActionBar">
  <item name="colorPrimary">@color/...</item>

Etc..
...

确保您的 AndroidManifest.xml 指向您定义的主题:

<application
    android:theme="@style/Theme.MyApplication"
    ...

至少定义您的 Activity 以在清单中使用所述主题:

        <activity
            android:name="com.your.WhateverActivity"
            android:theme="@style/Theme.MyApplication" />

Activity 本身的 kotlin/java 代码呢?

根据您的解决方案(使用主题或提供您自己的主题),您将需要或多或少的代码。

如果您选择使用 DarkActionBar(或光!),那么您不需要任何其他东西。您的“ActionBar”已为您设置好。您也不需要 XML 中的任何内容。只需 setContentView(R.layout.yourLayout) 就可以了。

如果您选择使用 NoActionBar 变体,那么您将不会有 ActionBar,除非您添加一个。

所以在你的 XML... 你将需要类似的东西(注意:这是默认布局随 Android 模板“空 Activity”,我删除了 TextView 并添加了 AppBarLAyout + Material 工具栏):

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:elevation="2dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.appbar.MaterialToolbar
            android:id="@+id/toolbar"
            style="@style/Widget.MaterialComponents.Toolbar.Primary"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </com.google.android.material.appbar.AppBarLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

现在 MainActivity.kt...

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val toolbar = findViewById<MaterialToolbar>(R.id.toolbar)
        setSupportActionBar(toolbar)
    }
}

如果主题是 NoActionBar,这将起作用,否则 setSupportActionBar 将抛出一个 IllegalStateException 说“你已经有一个操作栏”或类似的。有一个解决方法(您可以在主题中将“windowActionBar”设置为 false 以覆盖默认值,但如果是这种情况,我宁愿使用另一个主题)。

更新(Java)

Java真的没有太大区别。如果您的 Activity 在 Java 中,它看起来像这样:

import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }
}