详解Android首选项框架的使用

首选项这个名词对于熟悉Android的朋友们一定不会感到陌生,它经常用来设置软件的运行参数。

Android提供了一种健壮并且灵活的框架来处理首选项。它提供了简单的API来隐藏首选项的读取和持久化,并且提供了一个优雅的首选项界面。

首先,我们来看下面这款软件的首选项界面:

这款软件使用了好几种类型的首选项,每一种首选项都有其独特的用法,下面我们来了解一下几种常见的首选项:

CheckBoxPreference :用来打开或关闭某个功能

ListPreference :用来从多个选项中选择一个值;

EditTextPreference :用来配置一段文字信息;

Preference :用来执行相关的自定义操作(上图中的清除缓存、历史记录、表单、cookie都属于此项);

RingtonePreference :专门用来为用户设置铃声。

当我们使用首选项框架时,用户每更改一项的值后,系统就会立即在/data/data/[PACKAGE_NAME]/shared_prefs 下生成一个[PACKAGE_NAME]_preferences.xml 的文件,文件会记录最新的配置信息。

那么如何使用首选想框架呢?我们需要以下几步操作:

1.建立一个首选项的xml配置文件,放在项目的/res/xml目录下面;

2.新建一个Activity,继承android.preference.PreferenceActivity ,然后在onCreate方法中加载我们的首选项配置文件。

下面,我就为大家演示一下首选项框架的配置和使用:

我们新建一个prefs项目,项目结构如下:

我们要实现的功能跟上面那款软件的很相似,下面我来说明一下这个项目的整体流程:

1.主界面。显示用户昵称,有三个参数,昵称文字、字体大小和背景颜色。首次进入时,使用默认值。

2.按下menu键中的settings项,跳转到首选项页面,进行参数选择。

3.按下返回键,返回主界面,设定后的参数生效。

首先,让我们来看一下主界面的配置文件,非常简单,就一个TextView:

  1. <? xml   version = "1.0"   encoding = "utf-8" ?>   
  2. < LinearLayout   xmlns:android = "http://schemas.android.com/apk/res/android"   
  3.     android:orientation = "vertical"   
  4.     android:layout_width = "fill_parent"   
  5.     android:layout_height = "fill_parent" >   
  6.     < TextView   
  7.         android:id = "@+id/textView"   
  8.         android:layout_width = "fill_parent"   
  9.         android:layout_height = "fill_parent"   
  10.         android:gravity = "center_horizontal"   
  11.         android:textColor = "#FF0000" />   
  12. </ LinearLayout >   

然后,我们需要在主界面里根据配置参数设置TextView的外观以及背景,MainActivity.java代码如下:

  1. package  com.scott.prefs;  
  2.   
  3. import  android.app.Activity;  
  4. import  android.content.Context;  
  5. import  android.content.Intent;  
  6. import  android.content.SharedPreferences;  
  7. import  android.graphics.Color;  
  8. import  android.os.Bundle;  
  9. import  android.view.Menu;  
  10. import  android.view.MenuItem;  
  11. import  android.widget.TextView;  
  12.   
  13. public   class  MainActivity  extends  Activity {  
  14.       
  15.     private   static   final   int  SETTINGS_ID =  0 ;  
  16.     private   static   final   int  EXIT_ID =  1 ;  
  17.       
  18.     private  TextView textView;  
  19.       
  20.     @Override   
  21.     public   void  onCreate(Bundle savedInstanceState) {  
  22.         super .onCreate(savedInstanceState);  
  23.         setContentView(R.layout.main);  
  24.         textView = (TextView) findViewById(R.id.textView);  
  25.         showSettings();  
  26.     }  
  27.       
  28.     @Override   
  29.     public   boolean  onCreateOptionsMenu(Menu menu) {  
  30.         super .onCreateOptionsMenu(menu);  
  31.         menu.add(0 , SETTINGS_ID,  0"Settings" );  
  32.         menu.add(0 , EXIT_ID,  0"Quit" );  
  33.         return   true ;  
  34.     }  
  35.       
  36.     @Override   
  37.     public   boolean  onOptionsItemSelected(MenuItem item) {  
  38.         if  (item.getItemId() == SETTINGS_ID) {  
  39.             Intent intent = new  Intent(MainActivity. this , PrefsActivity. class );  
  40.             //如果requestCode >= 0 则返回结果时会回调 onActivityResult()方法   
  41.             startActivityForResult(intent, 1 );  
  42.         } else  {  
  43.             finish();  
  44.         }  
  45.         return   true ;  
  46.     }  
  47.       
  48.     @Override   
  49.     protected   void  onActivityResult( int  requestCode,  int  resultCode, Intent data) {  
  50.         super .onActivityResult(requestCode, resultCode, data);  
  51.         showSettings();  
  52.     }  
  53.   
  54.     private   void  showSettings() {  
  55.         String prefsName = getPackageName() + "_preferences" ;    //[PACKAGE_NAME]_preferences   
  56.         SharedPreferences prefs = getSharedPreferences(prefsName, Context.MODE_PRIVATE);  
  57.   
  58.         String nickName = prefs.getString("nickName""机器人" );  
  59.         textView.setText("欢迎您:"  + nickName);  
  60.           
  61.         boolean  nightMode = prefs.getBoolean( "nightMode"false );  
  62.         textView.setBackgroundColor(nightMode ? Color.BLACK : Color.WHITE);  
  63.           
  64.         String textSize = prefs.getString("textSize""0" );  
  65.         if  (textSize.equals( "0" )) {  
  66.             textView.setTextSize(18f);  
  67.         } else   if  (textSize.equals( "1" )) {  
  68.             textView.setTextSize(22f);  
  69.         } else   if  (textSize.equals( "2" )) {  
  70.             textView.setTextSize(36f);  
  71.         }  
  72.     }  
  73. }  

可以看到,进入主界面之后会根据[PACKAGE_NAME]_preferences获取首选项配置信息,如果是首次进入,则使用默认值,下面就是我们首次进入主界面时的画面:

可以看到,我们初次进入的界面时昵称为“机器人”,字的背景为白色,字的大小为18号。

然后按下Settings之后,我们就可以进行首选项的配置了,让我们先来看一下settings.xml的配置:

  1. <? xml   version = "1.0"   encoding = "utf-8" ?>   
  2. < PreferenceScreen   xmlns:android = "http://schemas.android.com/apk/res/android"   
  3.     android:key = "settings"   
  4.     android:title = "软件设置" >   
  5.     < PreferenceCategory   
  6.         android:key = "basic"   
  7.         android:title = "基本设置" >   
  8.         < EditTextPreference   
  9.             android:key = "nickName"   
  10.             android:title = "昵称"   
  11.             android:defaultValue = "机器人" />   
  12.         < CheckBoxPreference   
  13.             android:key = "nightMode"   
  14.             android:title = "夜间模式"   
  15.             android:summaryOn = "已启用"   
  16.             android:summaryOff = "未启用" />   
  17.         < ListPreference   
  18.             android:key = "textSize"   
  19.             android:title = "文字大小"   
  20.             android:dialogTitle = "文字大小"   
  21.             android:entries = "@array/textSize_entry"   
  22.             android:entryValues = "@array/textSize_entry_value"   
  23.             android:defaultValue = "0" />   
  24.     </ PreferenceCategory >   
  25.     < PreferenceCategory   
  26.         android:key = "clean"   
  27.         android:title = "清除记录" >   
  28.         < Preference    
  29.             android:key = "cleanHistory"   
  30.             android:title = "清除历史记录"   />       
  31.     </ PreferenceCategory >   
  32. </ PreferenceScreen >   

其中,最外层是PreferenceScreen标签,代表一系列首选项的集合;然后,我们注意到PreferenceCategory 这一项,此标签代表一个类别,可以包含多个首选项;最后就是我们用于配置参数的首选项了。需要了解的是,PreferenceScreen也可以嵌套使用 ,也就是说上面的PreferenceCategory可以替换成PreferenceScreen。

此外,我们还需要了解一下文件中出现的几个常用标签属性:

android:key   选项的名称或键

android:title   选项的标题

android:summary   选项的简短摘要

android:entries   列表项的文本

android:entryValues   列表中每一项的值

android:dialogTitle   对话框标题

android:defalutValue   列表中选项的默认值

对于CheckBoxPreference还有两个特殊的属性

android:summaryOn   选项被选中时显示的摘要

android:summaryOff   选项未选中时显示的摘要

我们还可以看到,在ListPreference中,entries来自于textSize_entry,而entryValues来自于textSize_entry_value,这两项都在/res/values目录下的text_size.xml配置:

  1. <? xml   version = "1.0"   encoding = "utf-8" ?>   
  2. < resources >   
  3.     < string-array   name = "textSize_entry" >   
  4.         < item ></ item >   
  5.         < item ></ item >   
  6.         < item ></ item >   
  7.     </ string-array >   
  8.     < string-array   name = "textSize_entry_value" >   
  9.         < item > 0 </ item >   
  10.         < item > 1 </ item >   
  11.         < item > 2 </ item >   
  12.     </ string-array >   
  13. </ resources >   

配置完成之后,我们就剩下最后一步了,创建Activity,继承PreferenceActivity,加载首选项资源文件,处理相应的选项事件。

PrefsActivity.java代码如下:

  1. package  com.scott.prefs;  
  2.   
  3. import  android.app.AlertDialog;  
  4. import  android.content.DialogInterface;  
  5. import  android.os.Bundle;  
  6. import  android.preference.EditTextPreference;  
  7. import  android.preference.ListPreference;  
  8. import  android.preference.Preference;  
  9. import  android.preference.PreferenceActivity;  
  10. import  android.preference.PreferenceScreen;  
  11. import  android.widget.Toast;  
  12.   
  13. public   class  PrefsActivity  extends  PreferenceActivity  implements  Preference.OnPreferenceChangeListener {  
  14.   
  15.     private  EditTextPreference nickName;  
  16.     private  ListPreference textSize;  
  17.     private  Preference cleanHistory;  
  18.   
  19.     @Override   
  20.     public   void  onCreate(Bundle savedInstanceState) {  
  21.         super .onCreate(savedInstanceState);  
  22.         addPreferencesFromResource(R.xml.setttings);  
  23.         nickName = (EditTextPreference) findPreference("nickName" );  
  24.         textSize = (ListPreference) findPreference("textSize" );  
  25.         cleanHistory = findPreference("cleanHistory" );  
  26.           
  27.         //为nickName和textSize注册Preference.OnPreferenceChangeListener监听事件   
  28.         //当值更改时我们可以立即更新summary   
  29.         nickName.setOnPreferenceChangeListener(this );  
  30.         textSize.setOnPreferenceChangeListener(this );  
  31.           
  32.         initSummary();  
  33.     }  
  34.       
  35.     //初始化summary   
  36.     private   void  initSummary() {  
  37.         nickName.setSummary(nickName.getText());  
  38.           
  39.         setTextSizeSummary(textSize.getValue());  
  40.     }  
  41.       
  42.     private   void  setTextSizeSummary(String textSizeValue) {  
  43.         if  (textSizeValue.equals( "0" )) {  
  44.             textSize.setSummary("小" );  
  45.         } else   if  (textSizeValue.equals( "1" )) {  
  46.             textSize.setSummary("中" );  
  47.         } else   if  (textSizeValue.equals( "2" )) {  
  48.             textSize.setSummary("大" );  
  49.         }  
  50.     }  
  51.   
  52.     /**  
  53.      * 重写PreferenceActivity的onPreferenceTreeClick方法  
  54.      * 在首选项被点击时 做出相应处理操作  
  55.      */   
  56.     @Override   
  57.     public   boolean  onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {  
  58.         if  (preference == cleanHistory) {  
  59.             new  AlertDialog.Builder( this )  
  60.                     .setTitle("清除历史记录" )  
  61.                     .setMessage("是否真的要清除历史记录?" )  
  62.                     .setPositiveButton("是"new  DialogInterface.OnClickListener() {  
  63.                         @Override   
  64.                         public   void  onClick(DialogInterface dialog,  int  which) {  
  65.                             //cleaning history...   
  66.                             Toast.makeText(PrefsActivity.this"清除成功" , Toast.LENGTH_SHORT).show();  
  67.                         }  
  68.                     }).setNegativeButton("否"new  DialogInterface.OnClickListener() {  
  69.                         @Override   
  70.                         public   void  onClick(DialogInterface dialog,  int  which) {  
  71.                             dialog.dismiss();  
  72.                         }  
  73.                     }).create().show();  
  74.         }  
  75.         return   true ;  
  76.     }  
  77.       
  78.     /**  
  79.      * 重写Preference.OnPreferenceChangeListener的onPreferenceChange方法  
  80.      * 当首选项的值更改时 做出相应处理操作  
  81.      */   
  82.     @Override   
  83.     public   boolean  onPreferenceChange(Preference preference, Object newValue) {  
  84.         if  (preference == nickName) {  
  85.             nickName.setSummary(newValue.toString());  
  86.         } else   if  (preference == textSize) {  
  87.             setTextSizeSummary(newValue.toString());  
  88.         }  
  89.         return   true ;  
  90.     }  
  91. }  

最后,别忘了在AndroidManifest.xml中加入此Activity配置信息:

  1. < activity   android:name = ".PrefsActivity" />   

当然我们也可以配置一下<intent-filter></intent-filter>属性。

经过以上几步,我们的首选项配置就完成了,首次进入的界面如下:

然后我们分别更改昵称、夜间模式、文字大小,如下:

可以看到,当我们更改了选项的值之后,摘要部分已经设置为最新值了,此时在我们应用下的shared_prefs目录中生成一个com.scott.prefs_preferences.xml文件,如图:

内容如下:

  1. <? xml   version = '1.0'   encoding = 'utf-8'   standalone = 'yes'   ?>   
  2. < map >   
  3. < boolean   name = "nightMode"   value = "true"   />   
  4. < string   name = "nickName" > scott </ string >   
  5. < string   name = "textSize" > 2 </ string >   
  6. </ map >   

此时,我们按回退键,回到主界面,发现刚才的设置已经生效了:

可以看到,昵称已经更改成“scott”,字的背景已更改为黑色,字的大小已更改为36号。

如果我们在首选项界面按下清除历史记录一项,将会出现一下界面:

猜你喜欢

转载自blog.csdn.net/cz285933169/article/details/6528852