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

Android:使用Jetpack组件时如何为Preferences添加Toolbar?

嘿,我正好遇到过一模一样的问题,给你几个亲测有效的解决方案,你可以根据自己的项目情况来选:

方案一:给设置页面套个带Toolbar的容器Fragment

这个方案最直观,通过一个普通Fragment作为容器,把PreferenceFragmentCompat嵌套进去,同时在容器里添加自定义Toolbar:

  1. 先创建容器布局 fragment_settings_container.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">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/settings_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:elevation="4dp"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar" />

    <FrameLayout
        android:id="@+id/settings_fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>
  1. 创建容器Fragment SettingsContainerFragment:
class SettingsContainerFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_settings_container, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // 配置自定义Toolbar
        val toolbar = view.findViewById<Toolbar>(R.id.settings_toolbar)
        (activity as AppCompatActivity).setSupportActionBar(toolbar)
        (activity as AppCompatActivity).supportActionBar?.apply {
            setDisplayHomeAsUpEnabled(true)
            title = getString(R.string.settings_title)
        }
        
        // 嵌套加载PreferenceFragmentCompat
        childFragmentManager.beginTransaction()
            .replace(R.id.settings_fragment_container, SettingsFragment())
            .commit()
            
        // 处理返回按钮逻辑
        toolbar.setNavigationOnClickListener {
            findNavController().popBackStack()
        }
    }
}
  1. 最后把nav_graph.xml里原来的SettingsFragment替换成这个容器Fragment,跳转时导航到容器Fragment即可。
方案二:直接在PreferenceFragmentCompat里自定义布局

不想加额外容器的话,可以直接重写PreferenceFragmentCompat的onCreateView方法,把Toolbar嵌入进去:

  1. 创建带Toolbar的布局 fragment_settings_with_toolbar.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">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/settings_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:elevation="4dp"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar" />

    <FrameLayout
        android:id="@+id/preference_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>
  1. 修改你的SettingsFragment:
class SettingsFragment : PreferenceFragmentCompat() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // 先加载自定义布局
        val rootView = inflater.inflate(R.layout.fragment_settings_with_toolbar, container, false)
        val preferenceContainer = rootView.findViewById<FrameLayout>(R.id.preference_container)
        
        // 让Preference的内容加载到容器里
        val preferenceView = super.onCreateView(inflater, preferenceContainer, savedInstanceState)
        preferenceContainer.addView(preferenceView)
        
        // 配置Toolbar
        val toolbar = rootView.findViewById<Toolbar>(R.id.settings_toolbar)
        (activity as AppCompatActivity).setSupportActionBar(toolbar)
        (activity as AppCompatActivity).supportActionBar?.apply {
            setDisplayHomeAsUpEnabled(true)
            title = getString(R.string.settings_title)
        }
        
        toolbar.setNavigationOnClickListener {
            findNavController().popBackStack()
        }
        return rootView
    }

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.preferences, rootKey)
    }
}
方案三:在MainActivity中动态控制Toolbar

如果你的MainActivity本身已经有Toolbar,只是在设置页需要切换Toolbar的行为,可以通过导航监听来动态配置:

class MainActivity : AppCompatActivity() {

    private lateinit var navController: NavController
    private lateinit var drawerLayout: DrawerLayout
    private lateinit var toolbar: Toolbar

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        toolbar = findViewById(R.id.main_toolbar)
        setSupportActionBar(toolbar)
        drawerLayout = findViewById(R.id.drawer_layout)
        navController = findNavController(R.id.nav_host_fragment)
        
        // 监听页面导航变化
        navController.addOnDestinationChangedListener { _, destination, _ ->
            when (destination.id) {
                R.id.settingsFragment -> {
                    // 设置页显示返回按钮,修改标题
                    supportActionBar?.apply {
                        setDisplayHomeAsUpEnabled(true)
                        title = getString(R.string.settings_title)
                    }
                    // 锁定抽屉,防止侧滑
                    drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
                }
                else -> {
                    // 其他页面恢复抽屉菜单和默认标题
                    supportActionBar?.apply {
                        setDisplayHomeAsUpEnabled(false)
                        title = getString(R.string.app_name)
                    }
                    drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
                }
            }
        }
    }

    override fun onSupportNavigateUp(): Boolean {
        // 设置页点击返回按钮时回退,其他页面处理抽屉导航
        return if (navController.currentDestination?.id == R.id.settingsFragment) {
            navController.popBackStack()
            true
        } else {
            NavigationUI.navigateUp(navController, drawerLayout)
        }
    }
}

内容的提问来源于stack exchange,提问作者dev.farmer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:17:33