一、PreferenceFragment的引入:
PreferenceActivity是一个非常有用的基类,当我们开发Android项目时避免不了选项设置,这些设置习惯用Preference来保存。Android专门为这种Activity提供了便捷的基类PreferenceActivity。如果继承自Preference则不需要自己控制Preference的读写,PreferenceActivity会为我们处理一切。
PreferenceActivity与普通的Activity不同,它不是使用界面布局文件,而是使用选项设置的布局文件。
选项设置布局文件以PreferenceScreen作为根元素来表示定义一个参数设置界面布局。
从Android 3.0以后官方不再推荐直接让PreferenceActivity加载选项设置布局文件,而是建议使用PreferenceFragment,二者用法类似。所以今天就来学习一下。
下面的这张截图就是一个典型的例子:
我们会看到整个页面被分为几组:无线和网络、个人、账户、设备、系统。这个分组(或者叫分类)就是PreferenceCategory。
Wifi右边有开关,这一项就是CheckBoxPreference;其他还有ListPreference和EditTextPreference。
你的每一次设置,都会被Preference自动保存下来,这就是setting的数据持久化。每个Preference都是以键值对的形式保存下来的。
PreferenceActivity的继承关系图:(不推荐使用)
PreferenceFragment的继承关系图:(推荐使用)
二、在XML文件中Preference的种类:
根节点中一定是<PreferenceScreen> 元素,在这个元素中可以添加不同的Preference。常见的Preference控件有:
直接子类:DialogPreference, PreferenceGroup, RingtonePreference, TwoStatePreference 非直接子类: CheckBoxPreference , EditTextPreference , ListPreference , MultiSelectListPreference, PreferenceCategory, PreferenceScreen, SwitchPreference我们还是通过实际的例子来实现吧。
【实例】
先新建一个工程文件:
新建类PrefFragment.java,让其继承PreferenceFragment,并加载选项设置的布局文件:(核心代码是第6行和13行)
01.
1
package
com.example.m05_preffragment01;
02.
2
03.
3
import
android.os.Bundle;
04.
4
import
android.preference.PreferenceFragment;
05.
5
06.
<strong>
6
public
class
PrefFragment
extends
PreferenceFragment {
07.
</strong>
7
@Override
08.
8
public
void
onCreate(Bundle savedInstanceState) {
09.
9
// TODO Auto-generated method stub
10.
10
super
.onCreate(savedInstanceState);
11.
11
12.
<strong>
12
//从xml文件加载选项
13.
13
addPreferencesFromResource(R.xml.preferences);
14.
</strong>
14
}
15.
15
}
然后,在MainActivity.java中加载上面的Fragment:
01.
1
package
com.example.m05_preffragment01;
02.
2
03.
3
import
android.app.Activity;
04.
4
import
android.app.FragmentManager;
05.
5
import
android.app.FragmentTransaction;
06.
6
import
android.os.Bundle;
07.
7
08.
8
public
class
MainActivity
extends
Activity {
09.
9
10.
10
@Override
11.
11
protected
void
onCreate(Bundle savedInstanceState) {
12.
12
super
.onCreate(savedInstanceState);
13.
13
setContentView(R.layout.activity_main);
14.
14
15.
15
//加载PrefFragment
16.
16
FragmentManager fragmentManager = getFragmentManager();
17.
17
FragmentTransaction transaction = fragmentManager.beginTransaction();
18.
18
PrefFragment prefFragment =
new
PrefFragment();
19.
19
transaction.add(R.id.prefFragment, prefFragment);
20.
20
transaction.commit();
21.
21
22.
22
}
23.
23
24.
24
}
接下来的知识就是重头戏了,既然PrefFragment要加载选项设置的布局文件R.xml.preferences,那我们就来定义一下这个preferences.xml:
在res目录下新建立一个xml目录,在该目录中新建文件preferences.xml:
关于preferences.xml的文件里面的代码,请看下面这一段。
五、preference详解:
1、<PreferenceCategory>的方式进行分组:
preferences.xml举例如下:
01.
<?xml version=
'1.0'
encoding=
'utf-8'
?>
02.
<PreferenceScreen xmlns:android=
'http://schemas.android.com/apk/res/android'
>
03.
04.
<!-- 设置的类别 -->
05.
<PreferenceCategory
06.
android:key=
'mylocation'
07.
android:summary=
'我的位置'
08.
android:title=
'我的位置源'
>
09.
<CheckBoxPreference
10.
android:key=
'wireless_network'
11.
android:summary=
'使用<a href="http://www.it165.net/network/nwwx/" target="_blank" class="keylink">无线网络</a>查看应用程序中的位置'
12.
android:title=
'使用<a href="http://www.it165.net/network/nwwx/" target="_blank" class="keylink">无线网络</a>'
/>
13.
</PreferenceCategory>
14.
15.
<PreferenceCategory
16.
android:key=
'mymsg'
17.
android:summary=
'个人信息'
18.
android:title=
'个人信息'
>
19.
<EditTextPreference
20.
android:key=
'myname'
21.
android:title=
'请输入真实姓名'
22.
android:summary=
'姓名'
/>
23.
</PreferenceCategory>
24.
25.
</PreferenceScreen>
上方代码中,一个<PreferenceCategory>就是一个类别,单个的<PreferenceCategory>可以放入任意的Preference控件。我们在第一个类别中放入了CheckBoxPreference控件,在第二个类别中放入了EditTextPreference控件。运行效果如下:
运行时候,会自动在/data/data/<packagename>/shared_prefs/目录生成一个文本文件:
注:这个文本的文件名太长了,我们可以在上方PrefFragment.java的第13行代码后面加上这样一句话来修改文件名:(这里我将文件名修改为:mysetting)
1.
getPreferenceManager().setSharedPreferencesName(
'mysetting'
);
文本内容如下:
我们现在在CheckBoxPreference中打钩,然后在EditTextPreference中输入内容:
文本内容显示如下:
2、显示子屏幕subscreens方式的进行分组:
01.
1
<?xml version=
'1.0'
encoding=
'UTF-8'
?>
02.
2
<PreferenceScreen xmlns:android=
'http://schemas.android.com/apk/res/android'
03.
3
android:title=
'Settings'
>
04.
4
05.
5
<PreferenceScreen
06.
6
xmlns:android=
'http://schemas.android.com/apk/res/android'
07.
7
android:summary=
'settings about emotions'
08.
8
android:title=
'Emotions'
>
09.
9
<CheckBoxPreference
10.
10
android:defaultValue=
'true'
11.
11
android:summaryOff=
'No,I am sorry.'
12.
12
android:summaryOn=
'Yes,I love you!'
13.
13
android:title=
'Love me?'
>
14.
14
</CheckBoxPreference>
15.
15
<CheckBoxPreference
16.
16
android:defaultValue=
'false'
17.
17
android:summaryOff=
'No,you are a good person.'
18.
18
android:summaryOn=
'Yes,I hate you!'
19.
19
android:title=
'Hate me?'
>
20.
20
</CheckBoxPreference>
21.
21
</PreferenceScreen>
22.
22
23.
23
<PreferenceScreen
24.
24
xmlns:android=
'http://schemas.android.com/apk/res/android'
25.
25
android:summary=
'settings about relations'
26.
26
android:title=
'Relations'
>
27.
27
<CheckBoxPreference
28.
28
android:defaultValue=
'true'
29.
29
android:summaryOff=
'No,I am sorry.'
30.
30
android:summaryOn=
'Yes,we are family!'
31.
31
android:title=
'Family?'
>
32.
32
</CheckBoxPreference>
33.
33
<CheckBoxPreference
34.
34
android:defaultValue=
'false'
35.
35
android:summaryOff=
'No,I am sorry.'
36.
36
android:summaryOn=
'Yes,we are friends!'
37.
37
android:title=
'Friends?'
>
38.
38
</CheckBoxPreference>
39.
39
</PreferenceScreen>
40.
40
41.
41
</PreferenceScreen>
运行效果如下:
点击上方第一个preference,进入下图中左侧界面;点击上方第二个preference,进入下图中右侧界面。效果如下:
3、ListPreference控件:
点击该控件后,将列出一个单选按钮的列表。用法如下:
01.
<?xml version=
'1.0'
encoding=
'utf-8'
?>
02.
<PreferenceScreen xmlns:android=
'http://schemas.android.com/apk/res/android'
>
03.
04.
<PreferenceCategory
05.
android:key=
'mylocation'
06.
android:summary=
'我的位置'
07.
android:title=
'我的位置源'
>
08.
<ListPreference
09.
android:key=
'mycities'
10.
android:title=
'所属城市'
11.
android:summary=
'点击弹出城市列表'
12.
android:dialogTitle=
'请选择城市'
13.
android:entries=
'@array/cities'
14.
android:entryValues=
'@array/cities'
/>
15.
</PreferenceCategory>
16.
17.
</PreferenceScreen>
上方代码中,PreferenceScreen为根标签,ListPreference为子标签。ListPreference的常见属性如下:
android:key 唯一标识符,和android:id相类似,PreferenceManager可以以其为参数通过findPreference获取指定的preference 。 注意,这个android:key的值也是Preference文件里面的XML“键”名 android:title 大标题 android:summary 标题下面的小字(这个要作为选项卡才有) android:entries 弹出的对话框中,列表显示的文本内容,注意哦,这里指定的是一个数组。 android:entryValues 与android:entries相对应的值 android:defaultValue 当对应值不存在时的默认值 android:dialogTitle 弹出的对话框中的标题信息关于android:entries和android:entryValues的区别,要强调一下:
android:entries :The human-readable array to present as a list. 是展现给用户的列表的值。 android:entryValues :he array to find the value to save for a preference when an entry from entries is selected. 展现的用户的选择列表的每个元素选择后,需要存储到手机中,这里的entryValues就是列表中各个元素被选择后存储到手机中的值(通过sharedPreferences保存在/data/data/<packagename>/shared_prefs/目录下)。简单的说就是此处是数据库中的值。上面的android:entries是展现给用户的列表的值。我们在上方代码中的第13、14行引用了数据,紧接着我们要在values目录下的strings.xml文件中定义这个被引用的城市列表(即数据来源):
01.
1
<?xml version=
'1.0'
encoding=
'utf-8'
?>
02.
2
<resources>
03.
3
04.
4
<string name=
'app_name'
>m05_PrefFragment01</string>
05.
5
<string name=
'action_settings'
>Settings</string>
06.
6
<string name=
'hello_world'
>Hello world!</string>
07.
7
08.
<strong>
8
<string-array name=
'cities'
>
09.
9
<item>成都</item>
10.
10
<item>重庆</item>
11.
11
<item>黄冈</item>
12.
12
</string-array></strong>
13.
13
14.
14
</resources>
上方代码中,8至12行:即加粗部分,是我添加的数据源。
运行程序效果如下:
六、监听事件onPreferenceTreeClick()方法:
1.
public
boolean
onPreferenceTreeClick(PreferenceScreen preferenceScreen Preference preference)
当任何一个preference控件被点击,都将触发该方法。但是可以通过preference.getKey()这个方法找到具体是哪个preference被点击了,因为每个preference的key都是唯一的。
【实例】
现将preferences.xml这个设置选项的布局文件,定义如下:
01.
<?xml version=
'1.0'
encoding=
'utf-8'
?>
02.
<PreferenceScreen xmlns:android=
'http://schemas.android.com/apk/res/android'
>
03.
04.
<!-- 设置的类别 -->
05.
<PreferenceCategory
06.
android:key=
'mylocation'
07.
android:summary=
'我的位置'
08.
android:title=
'我的位置源'
>
09.
<CheckBoxPreference
10.
android:key=
'wireless_network'
11.
android:summary=
'使用无线网络查看应用程序(例如Google地图)中的位置'
12.
android:title=
'使用无线网络'
/>
13.
<CheckBoxPreference
14.
android:key=
'gps_satellite_setting'
15.
android:summary=
'定位时,精确到街道级别(取消选择可节约电量)'
16.
android:title=
'启用GPS卫星设置'
/>
17.
</PreferenceCategory>
18.
19.
<PreferenceCategory
20.
android:key=
'mymessage'
21.
android:summary=
'个人信息设置'
22.
android:title=
'个人信息设置'
>
23.
<CheckBoxPreference
24.
android:key=
'yesno_save_individual_info'
25.
android:title=
'是否保存个人信息'
/>
26.
<EditTextPreference
27.
android:key=
'individual_name'
28.
android:summary=
'请输入真实姓名'
29.
android:title=
'姓名 '
/>
30.
<ListPreference
31.
android:entries=
'@array/cities'
32.
android:entryValues=
'@array/cities'
33.
android:key=
'mycity'
34.
android:summary=
'所属城市'
35.
android:title=
'所属城市'
/>
36.
</PreferenceCategory>
37.
38.
</PreferenceScreen>
运行效果如下:
现在我们需要做的是,选中上方红框中的CheckBoxPreference,对应下面的EditTextPreference为编辑状态;否则,如果CheckBoxPreference没有被选中,则EditTextPreference为不可编辑状态。修改PrefFragment.java的代码,其完整版代码如下:
01.
1
package
com.example.m05_preffragment01;
02.
2
03.
3
import
android.os.Bundle;
04.
4
import
android.preference.CheckBoxPreference;
05.
5
import
android.preference.EditTextPreference;
06.
6
import
android.preference.Preference;
07.
7
import
android.preference.PreferenceFragment;
08.
8
import
android.preference.PreferenceScreen;
09.
9
10.
10
public
class
PrefFragment
extends
PreferenceFragment {
11.
11
12.
12
@Override
13.
13
public
void
onCreate(Bundle savedInstanceState) {
14.
14
// TODO Auto-generated method stub
15.
15
super
.onCreate(savedInstanceState);
16.
16
17.
17
//从xml文件加载选项
18.
18
addPreferencesFromResource(R.xml.preferences);
19.
19
}
20.
20
21.
21
@Override
22.
22
public
boolean
onPreferenceTreeClick(PreferenceScreen preferenceScreen,
23.
23
Preference preference) {
24.
24
//如果“保存个人信息”这个按钮被选中,将进行括号里面的操作
25.
25
if
(
'yesno_save_individual_info'
.equals(preference.getKey())) {
26.
26
CheckBoxPreference checkBoxPreference = (CheckBoxPreference)findPreference(
'yesno_save_individual_info'
);
27.
27
EditTextPreference editTextPreference = (EditTextPreference)findPreference(
'individual_name'
);
28.
28
//让editTextPreference和checkBoxPreference的状态保持一致
29.
29
editTextPreference.setEnabled(checkBoxPreference.isChecked());
30.
30
}
31.
31
// TODO Auto-generated method stub
32.
32
return
super
.onPreferenceTreeClick(preferenceScreen, preference);
33.
33
}
34.
34
}
代码解释:
当任何一个preference控件被点击,都将触发onPreferenceTreeClick()方法(22行),但是可以通过preference.getKey()这个方法找到具体是哪个preference被点击(25行)。
26行、27行:通过public Preference findPreference(CharSequence key)找到对应的preference,然后强转为它的子类。
29行:核心代码,让editTextPreference和checkBoxPreference的状态保持一致。
运行效果如下:
这样,我们的功能就实现了。
文章来源:http://www.cnblogs.com/smyhvae/p/4020469.html