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

Android多Activity差异化Toolbar复用:替代重复代码的优化方案咨询

完全懂你的痛点!重复写Toolbar的配置代码确实烦,尤其是每个页面只有小差异的时候。咱们可以用自定义Toolbar+基类Activity的方式来解决,完美实现类似PHP动态头部的效果,既统一又能灵活调整。

解决方案:自定义通用Toolbar + 基类Activity

1. 先写通用Toolbar布局

把所有页面共有的元素(比如返回按钮、标题)固定下来,留出可变区域放每个页面独有的控件:

<!-- res/layout/layout_toolbar_common.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar_common"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="4dp"
    app:titleTextColor="@android:color/white">

    <!-- 固定左侧返回按钮(默认显示,可隐藏) -->
    <ImageView
        android:id="@+id/toolbar_back_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:src="@drawable/ic_back_white" />

    <!-- 居中自定义标题(替代系统默认标题) -->
    <TextView
        android:id="@+id/toolbar_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textSize="18sp"
        android:textColor="@android:color/white"
        android:text="默认标题" />

    <!-- 可变容器:放每个页面独有的按钮/视图 -->
    <LinearLayout
        android:id="@+id/toolbar_custom_container"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        android:orientation="horizontal"
        android:gravity="center_vertical"
        android:paddingEnd="16dp">
    </LinearLayout>

</androidx.appcompat.widget.Toolbar>

2. 封装基类Activity处理通用逻辑

写一个BaseToolbarActivity,把所有重复的Toolbar初始化、点击事件等逻辑都放这里,同时给子类留出自定义的入口:

abstract class BaseToolbarActivity : AppCompatActivity() {

    protected lateinit var toolbar: Toolbar
    protected lateinit var customContainer: LinearLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(getLayoutResId())
        initToolbar()
        // 让子类处理自定义差异
        setupCustomToolbar()
    }

    // 子类必须返回自己的布局ID(布局里要include通用Toolbar)
    abstract fun getLayoutResId(): Int

    private fun initToolbar() {
        toolbar = findViewById(R.id.toolbar_common)
        customContainer = findViewById(R.id.toolbar_custom_container)
        setSupportActionBar(toolbar)
        // 隐藏系统自带标题,用我们的自定义TextView
        supportActionBar?.setDisplayShowTitleEnabled(false)

        // 默认返回按钮逻辑,子类可重写
        findViewById<ImageView>(R.id.toolbar_back_btn).setOnClickListener {
            onBackPressedDispatcher.onBackPressed()
        }
    }

    // 子类重写这个方法,实现自己的Toolbar差异
    open fun setupCustomToolbar() {
        // 默认空实现,按需扩展
    }

    // 公共方法:设置标题
    protected fun setToolbarTitle(title: String) {
        findViewById<TextView>(R.id.toolbar_title).text = title
    }

    // 公共方法:隐藏返回按钮
    protected fun hideBackButton() {
        findViewById<ImageView>(R.id.toolbar_back_btn).visibility = View.GONE
    }

    // 公共方法:向可变区域添加自定义视图
    protected fun addCustomView(view: View) {
        customContainer.addView(view)
    }
}

3. 子类Activity轻松自定义

每个子类Activity只需要继承BaseToolbarActivity,然后在自己的布局里include通用Toolbar,再重写方法处理差异即可:

示例:首页Activity(无返回按钮,有搜索按钮)

首先是布局activity_home.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"
    android:orientation="vertical">

    <!-- 引入通用Toolbar -->
    <include layout="@layout/layout_toolbar_common" />

    <!-- 页面其他内容 -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="首页内容" />

</LinearLayout>

然后是Activity代码:

class HomeActivity : BaseToolbarActivity() {

    override fun getLayoutResId(): Int {
        return R.layout.activity_home
    }

    override fun setupCustomToolbar() {
        super.setupCustomToolbar()
        // 设置标题
        setToolbarTitle("首页")
        // 隐藏返回按钮
        hideBackButton()
        // 添加搜索按钮
        val searchBtn = ImageView(this).apply {
            layoutParams = LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
            setPadding(16, 0, 0, 0)
            setImageResource(R.drawable.ic_search_white)
            setOnClickListener {
                Toast.makeText(this@HomeActivity, "搜索", Toast.LENGTH_SHORT).show()
            }
        }
        addCustomView(searchBtn)
    }
}

示例:详情页Activity(有返回按钮,有分享按钮)

class DetailActivity : BaseToolbarActivity() {

    override fun getLayoutResId(): Int {
        return R.layout.activity_detail
    }

    override fun setupCustomToolbar() {
        super.setupCustomToolbar()
        setToolbarTitle("详情页")
        // 添加分享按钮
        val shareBtn = ImageView(this).apply {
            layoutParams = LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
            setPadding(16, 0, 0, 0)
            setImageResource(R.drawable.ic_share_white)
            setOnClickListener {
                Toast.makeText(this@DetailActivity, "分享", Toast.LENGTH_SHORT).show()
            }
        }
        addCustomView(shareBtn)
    }
}

额外优化建议

  • 把Toolbar的样式(比如背景色、标题大小)放到styles.xml的主题属性里,用?attr/xxx引用,方便全局修改。
  • 如果某些页面需要完全不同的Toolbar结构,可以在子类中重写initToolbar方法,或者直接替换布局中的通用Toolbar(尽量少用,保持风格统一)。
  • 可以给基类增加更多公共方法,比如setToolbarBackground、setTitleTextColor,满足更多自定义需求。

这样一来,所有重复的Toolbar代码都被封装到基类里,子类只需要关注自己的差异化部分,完美解决了代码冗余问题,和你说的PHP动态头部思路完全一致,既统一又灵活!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:20:17