Android 12系统源码_Settings(一)认识Preference

前言

想刀一家公司的心事藏不住的,原本只了解一下Android系统应用Settings的配置开关列表中某个开关开启或关闭的时候,系统做了哪些响应操作,结果搞了半天发现完全看不懂。写界面就写界面吧,但是Settings模块完全没有使用Android常规UI那种方案,而是结合Preference重新搞了一套UI布局方案,这样我们要想研究或定制Settings模块的某些功能,就必须先对Preference这套UI布局方案有个简单的认识。

一、Preference

1.1、简介

在 Android 开发中,Preference 是用来构建用户界面的组件,它提供了一种简单而有效的方式来管理应用的设置和用户偏好。Preference 类及其相关类主要用于创建和管理用户界面中的设置选项,例如复选框、单选按钮、列表项等,允许用户调整应用的行为和外观。

1.2、主要的 Preference 类型

  • Preference:

Preference 是所有偏好设置类的基类,通常不直接使用,而是通过其子类进行扩展和使用。

  • CheckBoxPreference:

CheckBoxPreference 是一个复选框偏好设置,允许用户通过勾选或取消勾选来控制一个布尔值设置项。

  • ListPreference:

ListPreference 允许用户从一个固定的列表中选择一个选项,例如选择语言、主题等。

  • EditTextPreference:

EditTextPreference 允许用户输入文本,通常用于需要用户输入自定义内容的设置项。

  • SwitchPreference:

SwitchPreference 是一个开关偏好设置,与 CheckBoxPreference 类似,但使用了开关样式而不是复选框。

  • PreferenceCategory:

PreferenceCategory 可以用来将多个相关联的偏好设置项组织到一个类别中,以改善界面的结构和可读性。

二、Preference简单实例

Android系统Settings模块通常大量使用了Preference来构建UI视图,如果直接去看基本都会一脸蒙蔽,这里我们使用Preference编写一个最简单的案例,只要看懂了这个案例,再去分析Settings模块使用Preference所构建的UI视图,基本就柳暗花明了。

2.1、创建 Preference XML 文件

在 res/xml 目录下创建一个 XML 文件,定义应用的偏好设置结构和各个设置项的属性。

res/xml/root_preferences.xml

xml 复制代码
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">

    <PreferenceCategory app:title="@string/messages_header">

        <EditTextPreference
            app:key="signature"
            app:title="@string/signature_title"
            app:useSimpleSummaryProvider="true" />

        <ListPreference
            app:defaultValue="reply"
            app:entries="@array/reply_entries"
            app:entryValues="@array/reply_values"
            app:key="reply"
            app:title="@string/reply_title"
            app:useSimpleSummaryProvider="true" />

    </PreferenceCategory>

    <PreferenceCategory app:title="@string/sync_header">

        <SwitchPreferenceCompat
            app:key="sync"
            app:title="@string/sync_title" />

        <SwitchPreferenceCompat
            app:dependency="sync"
            app:key="attachment"
            app:summaryOff="@string/attachment_summary_off"
            app:summaryOn="@string/attachment_summary_on"
            app:title="@string/attachment_title" />

    </PreferenceCategory>
    
</PreferenceScreen>

res/values/arrays.xml

xml 复制代码
<resources>
    <!-- Reply Preference -->
    <string-array name="reply_entries">
        <item>Reply</item>
        <item>Reply to all</item>
    </string-array>

    <string-array name="reply_values">
        <item>reply_value</item>
        <item>reply_all_value</item>
    </string-array>
</resources>

res/values/strings.xml

xml 复制代码
<resources>
    <string name="app_name">SettingsDemoApplication</string>
    <string name="title_activity_settings">SettingsActivity</string>

    <!-- Preference Titles -->
    <string name="messages_header">Messages</string>
    <string name="sync_header">Sync</string>

    <!-- Messages Preferences -->
    <string name="signature_title">Your signature</string>
    <string name="reply_title">Default reply action</string>

    <!-- Sync Preferences -->
    <string name="sync_title">Sync email periodically</string>
    <string name="attachment_title">Download incoming attachments</string>
    <string name="attachment_summary_on">Automatically download attachments for incoming emails
    </string>
    <string name="attachment_summary_off">Only download attachments when manually requested</string>
</resources>

2.2、创建PreferenceFragmentCompat类

创建一个 Java 类继承自 PreferenceFragmentCompat,并在其中加载上述 XML 文件。

java 复制代码
public class SettingsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.root_preferences, rootKey);
    }
    
}

2.3、在 Activity 中显示PreferenceFragmentCompat

新建一个Activity,并在该Activity中将 SettingsFragment 添加到布局中。

com/example/settings/SettingsActivity.java

java 复制代码
public class SettingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);
        //加载SettingsFragment
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.settings_container, new SettingsFragment())
                .commit();
    }
}

res/layout/settings_activity.xml

java 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

2.4、UI效果图视图

使用Preference只要经过上面的简单配置就能实现下面的效果图了。

2.5、监听Preference控件的状态变化

java 复制代码
public class SettingsFragment extends PreferenceFragmentCompat {

    public static final String TAG = "SettingsFragment";

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.root_preferences, rootKey);
        //监听Preference的状态
        EditTextPreference editTextPreference = findPreference("signature");
        editTextPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
                //回调日志打印
                Log.i(TAG, "onPreferenceChange preference = " + preference + ", newValue = " + newValue);
                return false;
            }
        });
        ListPreference listPreference = findPreference("reply");
        listPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
                //回调日志打印
                Log.i(TAG, "onPreferenceChange preference = " + preference + ", newValue = " + newValue);
                return false;
            }
        });
        SwitchPreferenceCompat switchPreferenceSync = findPreference("sync");
        switchPreferenceSync.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
                //回调日志打印
                Log.i(TAG, "onPreferenceChange preference = " + preference + ", newValue = " + newValue);
                return false;
            }
        });
        SwitchPreferenceCompat switchPreferenceAttachment = findPreference("attachment");
        switchPreferenceAttachment.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
                //回调日志打印
                Log.i(TAG, "onPreferenceChange preference = " + preference + ", newValue = " + newValue);
                return false;
            }
        });
    }
}

这样在我们对各个控件进行操作的时候,就能收到对应控件的状态变化了。

java 复制代码
2024-08-03 01:08:39.808  3249-3249  SettingsFragment        com.example.settings                 I  onPreferenceChange preference = Your signature 未设置, newValue = 123456
2024-08-03 01:08:42.778  3249-3249  SettingsFragment        com.example.settings                 I  onPreferenceChange preference = Default reply action 未设置, newValue = reply_value
2024-08-03 01:08:49.891  3249-3249  SettingsFragment        com.example.settings                 I  onPreferenceChange preference = Sync email periodically, newValue = true

三、Preference小结

简单列举下常见的Preference组件和标签。

4.1 常见组件

java 复制代码
(1) PreferenceScreen:根节点,代表一个偏好设置的屏幕。它是其他Preference组件的容器。
(2) EditTextPreference:允许用户输入文本值的偏好设置。
(3) CheckBoxPreference(在新版中被`SwitchPreferenceCompat`替代):提供一个开关按钮供用户开启或关闭某个设置。
(4) SwitchPreferenceCompat:与CheckBoxPreference功能类似,提供一个滑动开关供用户切换设置。
(5) ListPreference:显示一个选择列表,用户可以从中选择一个选项作为设置。
(6) MultiSelectListPreference:允许用户从列表中选择多个选项。
(7) PreferenceCategory:用于将偏好设置分组的类别标题。
(8) PreferenceFragmentCompat:一个Fragment,用于在其内部显示一个偏好设置的屏幕。

4.2 常见标签

java 复制代码
(1) key: 这个属性定义了偏好设置的唯一标识符。通过这个键,你可以在代码中检索或更新偏好设置的值。
(2) title: 设置项的标题,这是用户在设置界面看到的文本。
(3) summary: 设置项的摘要或描述,显示在标题下方,用于提供更多关于设置项的信息。
(4) defaultValue: 定义设置项的默认值。当应用第一次运行,且用户尚未更改过该设置时,将使用此默认值。
(5) widgetLayout: 允许开发者为偏好设置项指定一个自定义的布局。
(6) dependency: 这个属性使当前偏好设置依赖于另一个偏好设置的值。例如,如果一个偏好设置项被禁用,直到另一个特定的偏好设置被激活/选中。
(7) enabled: 控制偏好设置是否可用。默认为 true,即默认情况下是启用状态。
(8) selectable: 控制偏好设置项是否可以被选中。默认为 true。
(9) icon: 给设置项指定一个图标,以增加可识别性。
(10) fragment: 指定当偏好设置被选中时,应该启动的Fragment的全名。这对于构建多层次的设置界面很有用。
相关推荐
m0_748235954 小时前
CentOS 7使用RPM安装MySQL
android·mysql·centos
ac-er88887 小时前
Yii框架中的队列:如何实现异步操作
android·开发语言·php
流氓也是种气质 _Cookie9 小时前
uniapp 在线更新应用
android·uniapp
zhangphil11 小时前
Android ValueAnimator ImageView animate() rotation,Kotlin
android·kotlin
徊忆羽菲12 小时前
CentOS7使用源码安装PHP8教程整理
android
编程、小哥哥13 小时前
python操作mysql
android·python
Couvrir洪荒猛兽13 小时前
Android实训十 数据存储和访问
android
五味香16 小时前
Java学习,List 元素替换
android·java·开发语言·python·学习·golang·kotlin
十二测试录16 小时前
【自动化测试】—— Appium使用保姆教程
android·经验分享·测试工具·程序人生·adb·appium·自动化
Couvrir洪荒猛兽18 小时前
Android实训九 数据存储和访问
android