用 PreferenceFragment 构建分组设置界面:解读 cw-omnibus 中的 FragmentsBC 示例
示例工程教程【免费下载链接】cw-omnibusSource code to omnibus edition of _The Busy Coders Guide to Android Development_项目地址https://gitcode.com/gh_mirrors/cw/cw-omnibus点击查看免费下载本篇技术指南以 cw-omnibus 仓库The Busy Coders Guide to Android Development配套示例源码集中 Prefs/FragmentsBC/README.markdown 所述示例为核心系统讲解如何借助PreferenceFragment与PreferenceActivity的 header 机制把设置项拆分成多个分组页面。读完本文你将掌握loadHeadersFromResource()加载 header、addPreferencesFromResource()挂载偏好资源、isValidFragment()安全校验以及如何在普通 Fragment 中通过SharedPreferences回读偏好值这一整套实战方案。一、示例要解决的问题一个 Activity 管理多组设置Android 3.0API 11引入PreferenceFragment之后设置界面不再只能由PreferenceActivity单独承载 XML 资源而是可以把每一组设置放进一个 Fragment。FragmentsBC 示例即演示了这种一个设置页 多个偏好分组的组织形态主界面FragmentsDemo是一个普通 Activity仅通过菜单项进入设置页设置页EditPreferences继承PreferenceActivity重写onBuildHeaders()用 header 列表把两组设置串起来两个PreferenceFragment内部类First、Second分别承载两组不同的偏好选项返回主界面后PreferenceContentsFragment从默认SharedPreferences中读取所有设置结果并展示。该示例的配套书籍章节为《using preferences使用偏好设置》在仓库中的完整实现见 Prefs/FragmentsBC 目录。二、整体架构与入口流程2.1 三个 Java 类的分工类文件职责FragmentsDemoFragmentsDemo.java主界面展示当前偏好值菜单触发设置页EditPreferencesEditPreferences.javaPreferenceActivity子类负责 header 路由与 Fragment 白名单PreferenceContentsFragmentPreferenceContentsFragment.java普通 Fragment在onResume()中读取并刷新偏好显示2.2 从主界面到设置页主界面 FragmentsDemo.java 在onCreate()中加载 main.xml后者通过静态fragment标签直接嵌入了PreferenceContentsFragmentfragment xmlns:androidhttp://schemas.android.com/apk/res/android android:layout_widthmatch_parent android:layout_heightmatch_parent android:namecom.commonsware.android.preffragsbc.PreferenceContentsFragment/菜单方面actions.xml 定义了一个settings菜单项图标使用系统自带的android:drawable/ic_menu_preferences并设置showAsActionnever使其始终出现在溢出菜单。点击后经onOptionsItemSelected()启动EditPreferencesOverride public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.settings: startActivity(new Intent(this, EditPreferences.class)); return(true); } return(super.onOptionsItemSelected(item)); }对应地AndroidManifest.xml 中同时注册了主 Activity 与设置 Activity设置页无需LAUNCHER过滤器activity android:name.FragmentsDemo android:labelstring/app_name intent-filter action android:nameandroid.intent.action.MAIN/ category android:nameandroid.intent.category.LAUNCHER/ /intent-filter /activity activity android:name.EditPreferences android:labelstring/app_name/三、核心实现PreferenceActivity Header 路由3.1 onBuildHeaders 与 loadHeadersFromResourceEditPreferences的关键在于重写onBuildHeaders()把 header 资源喂给系统EditPreferences.java#L22-L26public class EditPreferences extends PreferenceActivity { Override public void onBuildHeaders(ListHeader target) { loadHeadersFromResource(R.xml.preference_headers, target); } ... }preference_headers.xml定义了两个分组入口每个header通过android:fragment指向要展示的PreferenceFragment全限定类名preference_headers.xmlpreference-headers xmlns:androidhttp://schemas.android.com/apk/res/android header android:fragmentcom.commonsware.android.preffragsbc.EditPreferences$First android:summarystring/header1summary android:titlestring/header1title /header header android:fragmentcom.commonsware.android.preffragsbc.EditPreferences$Second android:summarystring/header2summary android:titlestring/header2title /header /preference-headers注意类名的写法内部类使用$分隔即EditPreferences$First。title与summary分别来自 strings.xmlheader1titleSome Settings、header1summaryA handful of values for you to tailor、header2titleMore Settings 等。3.2 isValidFragmentAndroid 4.0 的强制安全闸门从 API 19 开始凡是使用 header 加载 Fragment 的PreferenceActivity系统会调用isValidFragment()校验传入的 Fragment 类名防止外部注入恶意 Fragment。示例中通过白名单方式放行自带的两个内部类EditPreferences.java#L29-L36Override protected boolean isValidFragment(String fragmentName) { if (First.class.getName().equals(fragmentName) || Second.class.getName().equals(fragmentName)) { return(true); } return(false); }从源码结构看这是基于 fragment 的偏好页面必不可少的配套代码一旦 header 引用的 Fragment 类名不在此白名单内isValidFragment()返回false系统将拒绝加载该 Fragment。3.3 两个 PreferenceFragment 内部类两个内部类都继承android.preference.PreferenceFragment在onCreate()里通过addPreferencesFromResource()各自加载一份偏好 XMLEditPreferences.java#L38-L54public static class First extends PreferenceFragment { Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); } } public static class Second extends PreferenceFragment { Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences2); } }First挂载的是 preferences.xmlSecond挂载的是 preferences2.xml。这样一个PreferenceActivity就能承载两个互相独立的设置分组用户通过 header 列表切换。四、偏好资源详解四类常用 Preferencepreferences.xml 聚合了 Android 平台四种最常见的偏好控件是理解PreferenceScreen子节点用法的绝佳范本PreferenceScreen xmlns:androidhttp://schemas.android.com/apk/res/android CheckBoxPreference android:keycheckbox android:summarystring/pref1summary android:titlestring/pref1title/ RingtonePreference android:keyringtone android:showDefaulttrue android:showSilenttrue android:summarystring/pref2summary android:titlestring/pref2title/ EditTextPreference android:dialogTitlestring/dialogtitle android:keytext android:summarystring/pref3summary android:titlestring/pref3title/ ListPreference android:dialogTitlestring/listdialogtitle android:entriesarray/cities android:entryValuesarray/airport_codes android:keylist android:summarystring/pref4summary android:titlestring/pref4title/ /PreferenceScreen各控件要点CheckBoxPreference开关型偏好android:keycheckbox即写入SharedPreferences的键名RingtonePreference铃声选择器android:showDefaulttrue让列表中出现默认铃声项android:showSilenttrue让列表中出现静音项EditTextPreference弹窗文本输入android:dialogTitle指定弹窗标题ListPreference弹窗单选列表android:entries是展示给用户的文本数组android:entryValues是实际写入存储的值数组两者通过数组下标一一对应。第二个分组 preferences2.xml 只包含一个CheckBoxPreferenceandroid:keycheckbox2用于验证多个 Fragment 分组各自独立维护 XML的模式。4.1 配套的数组资源arrays.xml 为ListPreference提供显示名与存储值的成对数据——以宾夕法尼亚州城市为显示名、机场三字码为存储值string-array namecities itemPhiladelphia/item itemPittsburgh/item itemAllentown/Bethlehem/item ... /string-array string-array nameairport_codes itemPHL/item itemPIT/item itemABE/item ... /string-array4.2 文本资源的组织strings.xml 统一维护了 header 标题/摘要、偏好标题/摘要、弹窗标题等文案如pref1titleCheckbox Preference、pref2summaryPick a tone, any tone、listdialogtitleChoose a Pennsylvania city。所有 XML 中均通过string/...引用避免了魔法字符串。五、回读偏好值PreferenceContentsFragment 的 onResume 刷新设置页修改的值保存在应用默认的SharedPreferences中。主界面的 PreferenceContentsFragment.java 在onResume()中统一读取——之所以放在onResume()而不是onCreateView()是为了保证用户从设置页返回时能拿到最新值Override public void onResume() { super.onResume(); SharedPreferences prefs PreferenceManager.getDefaultSharedPreferences(getActivity()); checkbox.setText(Boolean.valueOf(prefs.getBoolean(checkbox, false)).toString()); ringtone.setText(prefs.getString(ringtone, unset)); checkbox2.setText(Boolean.valueOf(prefs.getBoolean(checkbox2, false)).toString()); text.setText(prefs.getString(text, unset)); list.setText(prefs.getString(list, unset)); }要点PreferenceManager.getDefaultSharedPreferences()返回的是与 Preference UI 默认关联的那份偏好文件key 与 XML 中的android:key一一对应每个读取都提供了默认值如false、unset避免首次启动时空指针ringtone键存储的是铃声 URI 字符串checkbox、checkbox2用Boolean.valueOf(...)转为字符串展示。界面侧content.xml 用TableLayoutTableRow布局每行由一个加粗标签 TextView 和一个 30sp 的取值 TextView 组成标签与取值样式定义在 styles.xmllabel样式继承value样式并追加bold与 5dip 右内边距。六、工程配置与运行前提6.1 构建配置app/build.gradlecom.android.application插件compileSdkVersion 21、buildToolsVersion 26.0.2、targetSdkVersion 17根 build.gradleAndroid Gradle 插件版本3.1.4仓库源为google()与jcenter()settings.gradle仅包含:app模块AndroidManifest.xmlminSdkVersion14API 14即 Android 4.0targetSdkVersion14。6.2 主题适配主题在 themes.xml 中基于 Holo 系定义Theme.Holo.Light.DarkActionBar同时在 values-v21/styles.xml 中为 Android 5.0 提供了 Material 变体并指定colorPrimary、colorPrimaryDark、colorAccent三个主题色。运行该示例需要 API 14 以上的设备或模拟器。七、与同目录姊妹示例的横向对照在仓库 Prefs 目录下cw-omnibus 围绕偏好设置提供了多组渐进式示例方便对比不同组织方式示例特点Prefs/Fragment基础版单个PreferenceFragment不使用 headerPrefs/FragmentsBC本文多分组PreferenceActivity header 多个PreferenceFragmentPrefs/NestedScreens进阶在一个PreferenceScreen内嵌套另一个PreferenceScreenPrefs/CustomSubtitle自定义 Fragment 副标题Prefs/DataStore自定义偏好存储后端Prefs/SingleHeader 与 Prefs/SingleHeader2单 header 场景后者额外处理大屏布局对照可见FragmentsBC 的核心价值在于header 驱动的多分组路由它是 NestedScreens单页面内嵌套之外的另一条组织路径——把不同类别的设置拆到不同页面更适合设置项较多、需要按模块划分的应用。八、实战要点小结三层结构PreferenceActivity路由层→ header 资源分组层→PreferenceFragment内容层每层职责单一安全校验不能省API 19 必须重写isValidFragment()并返回白名单判断否则基于 header 的 Fragment 无法加载key 即存储键偏好 XML 中的android:key直接决定SharedPreferences中的键名回读时需保持一致回读时机选 onResume需要实时反映用户修改时把PreferenceManager.getDefaultSharedPreferences()的读取逻辑放在onResume()数组配对ListPreference的entries与entryValues按下标一一对应前者面向用户、后者面向存储。通过本文的源码级拆解你可以直接参考 Prefs/FragmentsBC 的完整实现在自己的应用中快速落地一个设置入口、多组 Fragment 化偏好页面的经典架构。赞分享示例工程教程【免费下载链接】cw-omnibusSource code to omnibus edition of _The Busy Coders Guide to Android Development_项目地址https://gitcode.com/gh_mirrors/cw/cw-omnibus点击查看免费下载相关推荐cw-omnibus 基础组件示例解读用 EditText 构建多行文本输入控件cw omnibus 基础组件示例解读用 EditText 构建多行文本输入控件 导读 本文聚焦 cw omnibus The Busy Coders G示例工程教程cw-omnibus 实战解读基于 SQLiteOpenHelper 的 SQLite 存储示例 ConstantsROWIDcw omnibus 实战解读基于 SQLiteOpenHelper 的 SQLite 存储示例 ConstantsROWID 本篇技术指南以 cw omni示例工程教程循环工程Loop Engineering概念溯源核心来源、思想谱系与仓库落地映射循环工程Loop Engineering概念溯源核心来源、思想谱系与仓库落地映射 导读 本文以仓库中的 Sources Attribution 来源文示例工程教程上一篇手机跑大模型30分钟用koboldcpp在Android上跑通本地AI推理终极实战指南下一篇【亲测免费】 layui-soul-table 项目常见问题解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

KBEngine 嵌入式 Python 整数对象 C API(PyLong)权威指南

KBEngine 嵌入式 Python 整数对象 C API(PyLong)权威指南

游戏开发后端 【免费下载链接】kbengine A MMOG engine of server. 项目地址: https://gitcode.com/gh_mirrors/kb/kbengine 点击查看 免费下载 本指南以 KBEngine 仓库内嵌的 CPython 3.7.3 官方文档 kbe/src/lib/python/Doc/c-api/long.rst 为骨架,逐…

2026/10/17 13:45:52 阅读更多 →
STM32F103_串口通信

STM32F103_串口通信

STM32F103C8T6 串口通信:轮询 / 中断 / DMA 三种方式,附 Keil 逻辑分析仪测波特率这次做的实验是 STM32 串口(USART)。要求挺全:先用 HAL 库实现最基本的串口收发,再把轮询、中断、DMA 三种方式都过一遍&am…

2026/10/17 13:45:52 阅读更多 →
【附源码】基于SpringBoot的在线骑行网站(源码+数据库+论文+答辩ppt一整套齐全)java开发springboot+vue框架javaweb,可做计算机毕业设计或课程设计

【附源码】基于SpringBoot的在线骑行网站(源码+数据库+论文+答辩ppt一整套齐全)java开发springboot+vue框架javaweb,可做计算机毕业设计或课程设计

🙊作者简介:多年一线开发工作经验,分享技术代码帮助学生学习。自有计算机毕设的工作室团队,专注计算机毕设开发、定制、远程、文档编写指导等。 🍅 查看主页更多项目 | 计算机毕设工作室 🍅 🍅 …

2026/10/17 14:41:13 阅读更多 →

最新新闻

开题答辩实战指南:以学生成绩管理系统为例

开题答辩实战指南:以学生成绩管理系统为例

开题答辩这东西,说大不大,说小不小。它基本上是毕业设计的第一道正式关卡,但很多同学把它想拧了,以为是要展示自己已经写了多少代码、做出多少功能。实际上开题答辩考察的是另一件事:你有没有把“要做什么、怎么做、能…

2026/10/18 14:10:21 阅读更多 →
生成式引擎优化实战:从显存墙到推理加速的完整指南

生成式引擎优化实战:从显存墙到推理加速的完整指南

先交代一下背景:我最近半年一直在折腾生成式模型的推理加速,从最早的单卡跑demo,到后面给内部的业务系统做服务化部署,中间踩了无数坑。这期间我花了不少时间研究各种优化手段,从最简单的量化,到张量并行、…

2026/10/18 14:10:21 阅读更多 →
Pandas入门教程(四):Series数据结构——创建、索引与常用方法

Pandas入门教程(四):Series数据结构——创建、索引与常用方法

一、什么是 Series?Series 是 Pandas 中的一个核心数据结构,类似于一个一维的数组,具有数据和索引。Series 可以存储任何数据类型(整数、浮点数、字符串等),并通过标签(索引)来访问元…

2026/10/18 14:10:21 阅读更多 →
鸿蒙适配 dart_nostr:从密钥签名到 Relay 订阅的完整实践

鸿蒙适配 dart_nostr:从密钥签名到 Relay 订阅的完整实践

把dart_nostr这个纯 Dart 组件往 HarmonyOS 上搬,最让人上头的不是编译,而是“Dart 都能跑,鸿蒙为什么不行”这种下意识判断带来的连锁翻车。项目本身不复杂:生成一对非对称密钥、构造并签名 Nostr 事件、连上 Relay 节点、发起订…

2026/10/18 14:10:21 阅读更多 →
verl源码深度拆解:从环境搭建到核心链路与调试实战

verl源码深度拆解:从环境搭建到核心链路与调试实战

简介:面向希望在7天内快速上手verl(Volcano Engine Reinforcement Learning for LLMs)框架的开发者,这份源码包提供了从单机部署到千万级参数模型训练全流程的完整代码与配置。包内共1058个文件,以Python脚本&#xff…

2026/10/18 14:10:21 阅读更多 →
多动作并行异步DDPG:选矿浮选智能决策模型工程化实践

多动作并行异步DDPG:选矿浮选智能决策模型工程化实践

简介:本资源是一篇发表于《控制与决策》2022年第8期的学术论文PDF,面向自动化、智能优化与流程工业领域的研究生、科研人员及工程技术人员,聚焦选矿过程运行指标的动态决策难题。针对传统深度确定性策略梯度(DDPG)算法…

2026/10/18 14:09:21 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →