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

Kotlin中无法用自定义Toolbar替换ActionBar问题求助

自定义Toolbar报错解决方案

我创建了一个自定义Toolbar并放置在Activity中,但遇到如下错误:

java.lang.IllegalStateException: Activity com.example.citiesdistance.feature.main.MainActivity@3a04806 does not have an ActionBar set via setSupportActionBar()

注意:
当显示默认ActionBar时,自定义Toolbar能正常工作,但会位于默认ActionBar下方。


相关代码

CustomToolbar类

class BaseToolbar(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
    private lateinit var binding: ViewToolbarBinding

    init {
        if (attrs != null) {
            binding = ViewToolbarBinding.inflate(LayoutInflater.from(context), this, true)
            val attr = context.obtainStyledAttributes(attrs, R.styleable.BaseToolbar)
            val title = attr.getString(R.styleable.BaseToolbar_bs_title)
            if (!title.isNullOrEmpty())
                binding.toolbarTitleTv.text = title
            attr.recycle()
        }
    }
}

view_toolbar.xml(自定义Toolbar布局)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="56dp"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <ImageView
        android:id="@+id/backBtn"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:scaleType="centerInside"
        android:background="?selectableItemBackgroundBorderless"
        android:layout_gravity="center_vertical|start"
        android:layout_marginStart="16dp"
        app:srcCompat="@drawable/ic_back"/>
    <TextView
        android:id="@+id/toolbarTitleTv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|start"
        android:layout_marginStart="56dp"
        style="?textAppearanceHeadline6"
        tools:text="نام صفحه"/>
</FrameLayout>

activity_main.xml

<?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"
    style="@style/WidthHeight.All.BothMatchParent"
    tools:context=".feature.main.MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.example.view.BaseToolbar
            android:id="@+id/testToolBar"
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"
            app:bs_title="Page 1" />
    </com.google.android.material.appbar.AppBarLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

themes.xml

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.CitiesDistance" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        .
        .
        .
    </style>
</resources>

显示效果

默认ActionBar显示效果

默认ActionBar显示效果

隐藏ActionBar显示效果

隐藏ActionBar显示效果


解决方案

错误核心原因:代码中可能调用了依赖系统ActionBar的API(如getSupportActionBar()),但当前主题为NoActionBar,且未通过setSupportActionBar()将自定义Toolbar设为替代ActionBar。

步骤1:修改自定义Toolbar继承关系

当前BaseToolbar继承自FrameLayout,无法直接作为ActionBar使用,需改为继承androidx.appcompat.widget.Toolbar:

class BaseToolbar(context: Context, attrs: AttributeSet?) : androidx.appcompat.widget.Toolbar(context, attrs) {
    private lateinit var binding: ViewToolbarBinding

    init {
        binding = ViewToolbarBinding.inflate(LayoutInflater.from(context), this, true)
        if (attrs != null) {
            val attr = context.obtainStyledAttributes(attrs, R.styleable.BaseToolbar)
            val title = attr.getString(R.styleable.BaseToolbar_bs_title)
            if (!title.isNullOrEmpty())
                binding.toolbarTitleTv.text = title
            attr.recycle()
        }
    }
}

步骤2:在Activity中设置自定义Toolbar为ActionBar

在MainActivity的onCreate方法中添加以下代码:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    val toolbar = findViewById<BaseToolbar>(R.id.testToolBar)
    setSupportActionBar(toolbar)
    
    // 隐藏系统默认标题,使用自定义标题
    supportActionBar?.setDisplayShowTitleEnabled(false)
}

步骤3:确认主题配置

确保themes.xml中的主题保持NoActionBar,避免默认ActionBar显示:

<style name="Theme.CitiesDistance" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <!-- 其他主题配置项 -->
</style>

额外优化

如果不需要AppBarLayout的滚动效果,可直接在布局中使用自定义Toolbar,减少层级:

<com.example.view.BaseToolbar
    android:id="@+id/testToolBar"
    android:layout_width="match_parent"
    android:layout_height="?actionBarSize"
    app:bs_title="Page 1"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"/>

内容的提问来源于stack exchange,提问作者Nima Khalili

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:25:00