一.基础知识
我们在使用Android手机时,可能会经常用到其中的设置界面,如下所示:
图1 Android系统中的设置界面
而且对于我们自己开发的一个完整的程序来说,我们也会需要给用户提供一个设置界面使用户可以对程序的一些参数进行设置。因此,我们就来学习下如何实现符合我们需要的一个设置界面,及其背后的数据持久化功能。
二.实例开发
2.1 SharedPreferences
在具体介绍Android的设置界面的实现之前,我们先来介绍一下预备知识,就是Android数据持久化方法中最简单的一种,即使用Preferences的键值对存储方式。这种方式主要用来存储比较简单的一些数据,而且是标准的Boolean、Int、Float、Long、String等类型。
android.content.SharedPreferences是一个接口,用来获取和修改持久化存储的数据。有三种获取系统中保存的持久化数据的方式:
1. public SharedPreferences getPreferences (int mode)
通过Activity对象获取,获取的是本Activity私有的Preference,保存在系统中的xml形式的文件的名称为这个Activity的名字,因此一个Activity只能有一个,属于这个Activity。
2. public SharedPreferences getSharedPreferences (String name, int mode)
因为Activity继承了ContextWrapper,因此也是通过Activity对象获取,但是属于整个应用程序,可以有多个,以第一参数的name为文件名保存在系统中。
3. public static SharedPreferences getDefaultSharedPreferences (Context context)
PreferenceManager的静态函数,保存PreferenceActivity中的设置,属于整个应用程序,但是只有一个,Android会根据包名和PreferenceActivity的布局文件来起一个名字保存。
通过以上方式取得SharedPreferences后就可以对数据进行读取或者保存了。
保存方式如下:
- String STORE_NAME = "Settings";
- SharedPreferences settings = getSharedPreferences(STORE_NAME, MODE_PRIVATE);
- SharedPreferences.Editor editor = settings.edit();
- editor.putInt("sourceType", 0);
- editor.commit();
获得SharedPreferences,如果需要进行保存等修改操作,首先得通过其edit()方法获得SharedPreferences.Editor,然后就可以通过putInt、putString等方法以键值对(key-value)的方式保存数据,或者remove移除某个键(key),及调用clear方法删除所有内容。最后需要调用commit方法是使修改生效。
读取方式如下:
- SharedPreferences settings = getSharedPreferences(STORE_NAME, MODE_PRIVATE);
- int source = settings.getInt("sorceType", 1);
读取就更加简单了,只要获得SharedPreferences后,就可以通过getInt、getString等方法获取对应键(key)保存着的数据,如果没有找到key,则返回第二个参数作为默认值。
2.2 PreferenceActivity
上面介绍SharedPreferences键值对保存的基础知识,接着我们就可以来实现Android系统的设置界面。Android系统中和设置界面相关的包为android.preference,其中有一个继承了ListActivity的PreferenceActivity。
下面我们就先实现一个如下图2的最简单的PreferenceActivity设置界面,只有一个CheckBox选择选项,选中时显示“Yes,I love you!”,取消选择时显示“No,I am sorry.”。然后再介绍其具体的实现。
图2 PreferenceActivity界面
首先新建一个工程AndroidPreferenceDemo。
把extends Activity改为extends PreferenceActivity。
在res目录下新建一个xml文件夹,接着在这个文件夹下新建一个取名为preferences.xml的File文件,内容如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="Settings">
- <CheckBoxPreference
- android:title="Love me?"
- android:summaryOn="Yes,I love you!"
- android:summaryOff="No,I am sorry."
- android:defaultValue="true">
- </CheckBoxPreference>
- </PreferenceScreen>
然后把java文件中的setContentView(R.layout.main);改为
addPreferencesFromResource(R.xml.preferences);
完成了,最后可以运行试下效果。
Java文件的实现很简单,继承PreferenceActivity后,调用其public void addPreferencesFromResource (int preferencesResId)
方法从一个xml文件中获取preference然后显示为标准的设置界面。
因此我们只要在xml文件中布局好要显示的设置界面内容就可以了。
下面我们看下布局文件xml的内容。
对应的xml中可以使用的标签(Tag)可以分为两类,一类是管理布局的显示,如PreferenceScreen;另一类是具体的设置内容,如CheckBoxPreference。
PreferenceScreen可以显示一个完整的页面,可以嵌套,包含在PreferenceScreen标签里的内容都将以一个完整的页面显示。
我们学习一个PreferenceScreen的界面,如下图3所示。
图3 PreferenceScreen相关的布局
当点击左图的选项时,分别会以新的页面显示,如中间和右图所示。
上面页面对应的xml布局文件如下所示:
- <?xml version="1.0" encoding="UTF-8"?>
- <PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="Settings">
- <PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="Emotions"
- android:summary="settings about emotions">
- <CheckBoxPreference
- android:title="Love me?"
- android:summaryOn="Yes,I love you!"
- android:summaryOff="No,I am sorry."
- android:defaultValue="true">
- </CheckBoxPreference>
- <CheckBoxPreference
- android:title="Hate me?"
- android:summaryOn="Yes,I hate you!"
- android:summaryOff="No,you are a good person."
- android:defaultValue="false">
- </CheckBoxPreference>
- </PreferenceScreen>
- <PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="Relations"
- android:summary="settings about relations">
- <CheckBoxPreference
- android:title="Family?"
- android:summaryOn="Yes,we are family!"
- android:summaryOff="No,I am sorry."
- android:defaultValue="true">
- </CheckBoxPreference>
- <CheckBoxPreference
- android:title="Friends?"
- android:summaryOn="Yes,we are friends!"
- android:summaryOff="No,I am sorry."
- android:defaultValue="false">
- </CheckBoxPreference>
- </PreferenceScreen>
- </PreferenceScreen>
和管理布局显示相关的除了PreferenceScreen外,还有一个常用的为PreferenceCategory,我们把上面xml文件中间那两个PreferenceScreen改为PreferenceCategory就可以看到PreferenceCategory的显示效果了,如下图4所示。
图4 PreferenceCategory相关的布局
可以看到PreferenceCategory是把包含的内容归为同一类,但只是显示在一个页面中。
管理布局相关的两个标签可以使设置内容显示的更有条理,但是更主要的还是具体设置相关的标签,除了我们已经在使用的用于二选一的CheckBoxPreference外,Android系统提供的还有以对话框显示的DialogPreference,可以输入文本的EditTextPreference,以列表方式显示供选择的ListPreference和设置铃声用的RingtonePreference。
下面我们选择比较常用的ListPreference来介绍下具体使用。
首先在res/values/文件夹下新建一个取名为array.xml的文件,内容为:
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <!-- 系统设置界面需要要到的数组 -->
- <string-array name="auto_update_frequency_entry">
- <item>10分钟</item>
- <item>30分钟</item>
- <item>1小时</item>
- <item>12小时</item>
- <item>24小时</item>
- </string-array>
- <string-array name="auto_update_frequency_value">
- <item>10</item>
- <item>30</item>
- <item>60</item>
- <item>720</item>
- <item>1440</item>
- </string-array>
- </resources>
然后在res/values/strings.xml文件中添加
- <!-- 统设置界面需要要到的字符串 -->
- <string name="system_settings">系统设置</string>
- <string name="auto_update_setting">自动更新设置</string>
- <string name="auto_update_switch_title">自动更新</string>
- <string name="auto_update_switch_key">auto_update_switch</string>
- <string name="auto_update_switch_summary_on">开启自动更新</string>
- <string name="auto_update_switch_summary_off">关闭自动更新</string>
- <string name="auto_update_frequency_title">更新频率</string>
- <string name="auto_update_frequency_key">auto_update_frequency</string>
- <string name="auto_update_frequency_default_value">10</string>
- <string name="auto_update_frequency_summary">设置自动更新的时间周期</string>
- <string name="cancel">取消</string>
需要的数据现在准备好了,下面我们来完成对应的xml文件。xml文件中各个标签的属性比较多,虽然Android有代码自动补全功能,但是还是使用Android提供的Structure界面来填写比较方便,下面我们就以这个方式来完成。
在res/xml文件夹下新建一个Android XML File文件,取名为preferencesii.xml,类型选择Preference,Root Element选择PreferenceScreen。 在Structure方式显示时,就会列出选中标签的所有属性,然后就可以根据需要填写属性,如下图5所示:
图5 填写xml中Preference的属性
从上图我们可以看到一个Preference拥有的属性。其中Key为这个Preference的ID,设置了才可以在代码中引用,Title是显示的标题,Summary是显示在标题下的文字介绍, 一般在Dependency中填写一个CheckBoxPreference的Key,这样就会在填写的那个CheckBoxPreference勾选时当前这个Preference才可用,Default Value为初始值,等等。
点击“Add”按钮,就会添加新的标签,我们依次添加一个CheckBoxPreference和ListPreference。属于CheckBoxPreference的特有属性主要为Summary On和Summary Off,比较好理解。下面具体来看下ListPreference属性的填写:
图6 ListPreference的属性
我们可以看到,ListPreference除了继承自Preference的属性外,还有自己ListPreference的属性和继承自DialogPreference的属性。其中属于ListPreference的属性有两个:Entries填的为一个字符串数组,是列表显示出来的值,而Entry Values是长度对应的字符串数组,是和Entries对应的具体的值。DialogPreference只要填一个Dialog title标题和一个取消按钮显示的字即可。在Preference属性的Dependency中我们填写上面一个CheckBoxPreference的Key,这样就会只有在CheckBoxPreference勾选时这个ListPreference才有效。
图7 完整的xml显示
最后把java文件中的addPreferencesFromResource(R.xml.preferences);改为addPreferencesFromResource(R.xml.preferencesii);
保存运行,看下效果。
图8 ListPreference显示
2.3 OnPreferenceChangeListener
以上我们分别介绍了Preference对数据的保存及PreferenceActivity设置界面。当PreferenceActivity中的内容改变时,Android系统会自动进行保存和持久化维护,我们只需要在要用的设置界面中数据的地方进行读取就可以了。同时Android还提供了OnPreferenceClickListener和OnPreferenceChangeListener两个与Preference相关的监听接口,当PreferenceActivity中的某一个Preference进行了点击或者改变的操作时,都会回调接口中的函数,这样可以第一个时间向其他Activity等通知系统设置进行了改变。
下面我们以一个具体的Demo说明PreferenceActivity和其监听接口的使用。
新建一个工程AndroidPreferenceDemoII,并按上面的步骤添加xml文件夹和其内容Preferenceii.xml,还有values文件夹中的array.xml和strings.xml。
新建一个名为Settings的class,内容为:
- //继承PreferenceActivity,并实现OnPreferenceChangeListener和OnPreferenceClickListener监听接口
- public class Settings extends PreferenceActivity implements OnPreferenceChangeListener,
- OnPreferenceClickListener{
- //定义相关变量
- String updateSwitchKey;
- String updateFrequencyKey;
- CheckBoxPreference updateSwitchCheckPref;
- ListPreference updateFrequencyListPref;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //从xml文件中添加Preference项
- addPreferencesFromResource(R.xml.preferencesii);
- //获取各个Preference
- updateSwitchKey = getResources().getString(R.string.auto_update_switch_key);
- updateFrequencyKey = getResources().getString(R.string.auto_update_frequency_key);
- updateSwitchCheckPref = (CheckBoxPreference)findPreference(updateSwitchKey);
- updateFrequencyListPref = (ListPreference)findPreference(updateFrequencyKey);
- //为各个Preference注册监听接口
- updateSwitchCheckPref.setOnPreferenceChangeListener(this);
- updateSwitchCheckPref.setOnPreferenceClickListener(this);
- updateFrequencyListPref.setOnPreferenceChangeListener(this);
- updateFrequencyListPref.setOnPreferenceClickListener(this);
- }
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- // TODO Auto-generated method stub
- Log.v("SystemSetting", "preference is changed");
- Log.v("Key_SystemSetting", preference.getKey());
- //判断是哪个Preference改变了
- if(preference.getKey().equals(updateSwitchKey))
- {
- Log.v("SystemSetting", "checkbox preference is changed");
- }
- else if(preference.getKey().equals(updateFrequencyKey))
- {
- Log.v("SystemSetting", "list preference is changed");
- }
- else
- {
- //如果返回false表示不允许被改变
- return false;
- }
- //返回true表示允许改变
- return true;
- }
- @Override
- public boolean onPreferenceClick(Preference preference) {
- // TODO Auto-generated method stub
- Log.v("SystemSetting", "preference is clicked");
- Log.v("Key_SystemSetting", preference.getKey());
- //判断是哪个Preference被点击了
- if(preference.getKey().equals(updateSwitchKey))
- {
- Log.v("SystemSetting", "checkbox preference is clicked");
- }
- else if(preference.getKey().equals(updateFrequencyKey))
- {
- Log.v("SystemSetting", "list preference is clicked");
- }
- else
- {
- return false;
- }
- return true;
- }
- }
主要是获取xml文件中的各个Preference,然后为其注册监听接口,最后在监听接口的回调函数中打印相关的信息。
接着在Manifest文件中对这个Activity进行注册:
- <activity android:name=".Settings">
- </activity>
然后对AndroidPreferenceDemoII.java文件进行如下修改:
- public class AndroidPreferenceDemoII extends Activity {
- /** Called when the activity is first created. */
- // 菜单项
- final private int menuSettings=Menu.FIRST;
- private static final int REQ_SYSTEM_SETTINGS = 0;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- //创建菜单
- @Override
- public boolean onCreateOptionsMenu(Menu menu)
- {
- // 建立菜单
- menu.add(0, menuSettings, 2, "设置");
- return super.onCreateOptionsMenu(menu);
- }
- //菜单选择事件处理
- @Override
- public boolean onMenuItemSelected(int featureId, MenuItem item)
- {
- switch (item.getItemId())
- {
- case menuSettings:
- //转到Settings设置界面
- startActivityForResult(new Intent(this, Settings.class), REQ_SYSTEM_SETTINGS);
- break;
- default:
- break;
- }
- return super.onMenuItemSelected(featureId, item);
- }
- //Settings设置界面返回的结果
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if(requestCode == REQ_SYSTEM_SETTINGS)
- {
- //获取设置界面PreferenceActivity中各个Preference的值
- String updateSwitchKey = getResources().getString(R.string.auto_update_switch_key);
- String updateFrequencyKey = getResources().getString(R.string.auto_update_frequency_key);
- //取得属于整个应用程序的SharedPreferences
- SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
- Boolean updateSwitch = settings.getBoolean(updateSwitchKey, true);
- String updateFrequency = settings.getString(updateFrequencyKey, "10");
- //打印结果
- Log.v("CheckBoxPreference_Main", updateSwitch.toString());
- Log.v("ListPreference_Main", updateFrequency);
- }
- else
- {
- //其他Intent返回的结果
- }
- }
- }
主要是添加一个设置菜单,点击后转到设置界面,当从设置界面返回后读取保存的内容,并打印出来查看。
最后我们看一下运行的效果:
图9 设置界面操作
操作的Log输出如下图10所示:
图10 DDMS的LogCat输出
点击设置菜单转到设置界面后,首先点击CheckBox,输出前6行,然后点击ListPreference,输出3行,当选择列表的第二个进行改变时,再输出3行,最后按返回键回到第一个页面,打印出最后2行。
最后我们看一下这些设置参数在系统中的保存文件。在DDMS的File Explorer中,查看data/data/com.ichliebephone文件夹,我们可以看到有如下文件:
图11 Preference保存的文件
把这个文件导出到电脑上,可以看到起内容为:
- <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
- <map>
- <string name="auto_update_frequency">30</string>
- <boolean name="auto_update_switch" value="true" />
- </map>
文件以map的方式保存了两个设置参数
三.总结
我们学习了Android的Preference相关内容,包括最基本的SharedPreferences的使用,及进一步的PreferenceActivity设置界面的介绍,最后根据以上的内容完成了一个简单的Demo。
Preference键值对的方式是Android最简单的一种数据持久化方式,虽然比较简单,但是也比较实用,特别是在保存小量的数据时。Android上的功能更加强大相对也更加复杂的SQLite数据保存方式我们以后接着学习。
文章对应的完整代码例子可以在这里下载:
http://download.csdn.net/source/2728956
转自:http://blog.csdn.net/ichliebephone/article/details/5916320
另外一个:
Android的配置界面PreferenceActivity
我想大家对于android的系统配置界面应该不会陌生吧,即便陌生,那么下面的界面应该似曾相识吧,假若还是不认识,那么也没有关系,我们这一节主要就是介绍并讲解android 中系统配置界面的使用,相信大家看完本节后,一定能知道怎么使用这些东西了。
从上述界面中(其实是一个界面),我们可以看到有2组元素,第一组为:自动更新,更新频率。第二组为:是否登录,账号,密码。
其实分组是为了方便管理而已。这里主要使用到了选择,列表,编辑框等Preference.
我们还是来温习下基础知识吧。
一.基础知识
通常我们开发一个程序时,会需要给用户提供一个设置界面,使用户可以对程序的一些参数进行设置。通常我们使用Preferences的键值对存储方式,来对Android数据持久化。
android.content.SharedPreferences是一个接口,用来获取和修改持久化存储的数据。有三种方式可以获取系统中持久化的数据,这些数据时存放在.xml中的:
1:public SharedPreferences getPreferences (int mode),只隶属于activity对象,并以这个对象为文件名。
2:public SharedPreferences getSharedPreferences (String name, int mode),隶属于整个应用,以name名称保存。
3:public static SharedPreferences getDefaultSharedPreferences (Context context),隶属于整个应用,保存PreferenceActivity中的设置,根据包名和PreferenceActivity的布局文件来起一个名字保存。
SharedPreferences可以保存Boolean、Int、Float、Long、String等类型。一般是SharedPreferences.Editor的putXXX()方法保存,并commit()方法提交;或者是remove(),方法移除,clear()方法清空,当然操作完毕后需要commit()方法提交。
一般的,可以使用SharedPreferences保存持久化数据,比如登陆账号,密码,以及相对固定设置参数等等,看你应用需要。
既然使用到设置参数界面,那么我们可以来认识下一下几个类标签:
1:PreferenceScreen 持久化设置界面的顶级容器,代表一屏,里面可以嵌套屏幕,嵌套的时候可以点击跳转到另外一屏。
2:PreferenceCategory 当前屏的分组容器,说白了,就是为了划分组而已。
3:CheckBoxPreference,ListPreference,EditTextPreference等等组件。这些都是常见的对应上述的选择标签、列表标签、编辑标签。
上述组件都有titile,summary,key属性。title标题描述,summary:详细描述,key:保存SharedPreferences时候的键。
二.实战
既然有了上述基础知识后,我们就可以来做如上的设置界面了,在上述界面中,我们知道当前配置界面只需一屏,没有额外的跳转,那么需要PreferenceScreen,不需要嵌套其他PreferenceScreen,而设置界面分为两栏,那么需要两个PreferenceCategory,并且这个PreferenceCategory可以设置标题。同时根据界面,我们还需要CheckBoxPreference,ListPreference,EditTextPreference等。操作如图:
当然了,我们还是实际操作下吧,然后实际联系理论(理论联系实际太抽象),我们首先编写使用工具选择标签,然后形成代码,存放在xml文件夹中,如下:
当然这里使用到了一些文件,代码一并释放:
接下来,我们就来解释下xml文件夹中设置文件的一些内容吧:
android:key="@string/update_key" 这个是我们持久化时SharedPreferences保存的键,
android:summaryOn="@string/auto_update_switch_summary_on" 选中后显示内容
android:summaryOff="@string/auto_update_switch_summary_off" 未选中后显示内容
android:summary="@string/auto_update_setting" 平常状态显示内容
android:title="@string/auto_update_switch_title" 标题
android:defaultValue="true" 默认值
android:dialogTitle="@string/auto_update_frequency_title" 对话框标题
android:entries="@array/auto_frequency_name" 列表项显示名称
android:entryValues="@array/auto_frequency_value" 列表项值
android:disableDependentsState="true" 当CheckBoxPreference的值为真的时候,禁用依赖于该设置的其他设置项。
android:dependency="@string/isneilflag_key" 根据上述设置依赖于CheckBoxPreference的真值进行启用与禁用。
注意:我们可以从上图知道ListPreference是继承之Preference,以及DialogPreference的,那么就有它们的属性以及方法了。
好了,设置界面已经定义完成,我们来定义一个activity继承之PreferenceActivity,并使之显示吧。
当然噩梦可以再使之继承接口OnPreferenceChangeListener,OnPreferenceClickListener,当PreferenceActivity中的某一个Preference进行了点击或者改变的操作时,都会回调接口中的函数。
具体代码如下:
从上述代码可知:
1:设置显示Preferences可以调用方法addPreferencesFromResource(R.xml.preference); 传递preference文件即可。
2:然后通过findPreference();方法找到键的类标签
3:我们定义2个监听接口监听参数是否设置成功。
4:在监听接口中返回true就是设置允许提交。
结果打印如下:
成功!
也许你会问,我们这里并没有使用
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
settings.getXXXX();settings.putXXXX();以及commit()等方法,设置、获取并提交值啊?!是的,在这里我们不需这样,因为
当PreferenceActivity中的内容改变时,Android系统会自动进行保存和持久化维护,我们只需要在要用的设置界面中数据的地方进行读取就可以了。
当然,您可以在其他界面使用SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);等类方法来获取数据,看能不能获取到
转自:
http://www.cnblogs.com/zhangdongzi/archive/2012/01/05/2313519.html