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

单Activity架构下如何为每个Fragment配置不同的Toolbar布局?

最优实现方案:Activity统一托管Toolbar,Fragment按需配置

针对你的单Activity多Fragment场景,推荐采用Activity统一托管Toolbar,结合Fragment生命周期绑定MenuProvider的方案,既避免了重复Toolbar的性能问题,又能彻底解决菜单残留、点击事件冲突的问题。

核心思路

  1. Activity仅负责初始化Toolbar的基础配置,将Toolbar的样式(标题、Home图标、菜单)和行为(Home点击逻辑)完全交给对应Fragment控制。
  2. 每个Fragment通过viewLifecycleOwner注册专属的MenuProvider,Fragment销毁时自动注销,避免菜单和点击事件残留。
  3. 封装Activity的Toolbar控制方法,让Fragment可以快速配置所需样式。

具体代码实现

1. MainActivity 改造

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var drawerLayout: DrawerLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        drawerLayout = binding.drawerLayout

        // 初始化Toolbar基础配置(不设置Home按钮/图标,交给Fragment处理)
        initToolbar()

        // 默认加载主Fragment
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.container, MainFragment())
                .commit()
        }
    }

    private fun initToolbar() {
        setSupportActionBar(binding.content.toolbar)
        supportActionBar?.setDisplayShowTitleEnabled(false)
    }

    // 对外暴露Toolbar配置方法,供Fragment调用
    fun updateToolbar(
        showHomeAsUp: Boolean,
        homeIndicatorResId: Int? = null,
        title: String
    ) {
        supportActionBar?.apply {
            setDisplayHomeAsUpEnabled(showHomeAsUp)
            homeIndicatorResId?.let { setHomeAsUpIndicator(it) }
        }
        binding.content.toolbar.title = title
    }

    // 提供DrawerLayout实例,供主Fragment调用
    fun getDrawerLayout(): DrawerLayout = drawerLayout
}

2. 主Fragment(带Drawer和菜单)

class MainFragment : Fragment() {
    private lateinit var menuProvider: MenuProvider

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 配置Toolbar:显示Drawer图标、设置标题
        (activity as MainActivity).updateToolbar(
            showHomeAsUp = true,
            homeIndicatorResId = R.drawable.ic_action_open_drawer,
            title = "主页面"
        )

        // 注册专属MenuProvider,绑定Fragment生命周期
        menuProvider = object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                menu.clear() // 确保清空之前的菜单
                menuInflater.inflate(R.menu.toolbar_main, menu) // 加载带两个选项的菜单
            }

            override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
                return when (menuItem.itemId) {
                    android.R.id.home -> {
                        (activity as MainActivity).getDrawerLayout().openDrawer(GravityCompat.START)
                        true
                    }
                    R.id.menu_option1 -> {
                        // 处理菜单选项1逻辑
                        true
                    }
                    R.id.menu_option2 -> {
                        // 处理菜单选项2逻辑
                        true
                    }
                    else -> false
                }
            }
        }
        requireActivity().addMenuProvider(menuProvider, viewLifecycleOwner)
    }
}

3. 其他Fragment(仅返回按钮)

class OtherFragment : Fragment() {
    private lateinit var menuProvider: MenuProvider

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 配置Toolbar:显示返回图标、设置标题
        (activity as MainActivity).updateToolbar(
            showHomeAsUp = true,
            homeIndicatorResId = R.drawable.ic_back_arrow,
            title = "其他页面"
        )

        // 注册空MenuProvider,处理返回逻辑
        menuProvider = object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                menu.clear() // 彻底清空菜单
            }

            override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
                return when (menuItem.itemId) {
                    android.R.id.home -> {
                        requireActivity().onBackPressedDispatcher.onBackPressed()
                        true
                    }
                    else -> false
                }
            }
        }
        requireActivity().addMenuProvider(menuProvider, viewLifecycleOwner)
    }
}

方案优势

  • 避免重复渲染:Activity统一托管Toolbar,无需每个Fragment单独添加,性能更优。
  • 彻底解决残留问题:通过viewLifecycleOwner绑定MenuProvider,Fragment销毁时自动注销,不会残留旧菜单和点击事件。
  • 职责清晰:每个Fragment自主控制自身对应的Toolbar样式和行为,代码耦合度低。
  • 扩展性强:后续新增Fragment时,只需按需调用updateToolbar并注册MenuProvider即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 22:00:29