您的位置:首页 > 移动开发 > Android开发

Android 管理和组织首选项 (Preference) 附示例

2012-04-06 21:48 363 查看



1.何为首选项(Preference)?

Preference翻译成首选项有点生硬,但似乎也找到不其他更好的翻译,preference在英语的翻译是“偏爱,优先权”的意思。

Android 首选项是用来在Android中读取和存储一些数据,通常是配置项,当然完全还有其他方式能实现,比如数据库或者文件,为什么要使用Android中首选项,个人的理解是一些配置文件存在数据库中还要一张表来存,而且只有一行数据,还要自己写读取和保存方法,实在是累的很。在这提下,Android中的首选项最终是把数据按一定格式存到XMl文件中的,最后我们可以看到,数据的具体样子。

2.看一些今天我们Android首选项的例子效果图(会因为手机主题不同而变化)









主Activity页面 图1 图2 图3

点击主Activity的按钮就会进入图1,如果“喜欢吃水果选款”是勾选状态,下面两个点击就会分别弹出右边的样式,不是勾选状态下面两个就会置灰,不可用。

3. 赶快来看下如何实现的:)

1.首先是preference的布局文件 /res/xml/fruitoptions.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory>
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/love_fruit_pref"
            android:summary="@string/love_fruit_summary"
            android:title="@string/love_fruit_title" />
    </PreferenceCategory>
    <PreferenceCategory android:key="@string/detailSetting" >
        <ListPreference
            android:defaultValue="@string/fruit_option_default_value"
            android:dialogTitle="@string/dialogTitle"
            android:entries="@array/fruit_options"
            android:entryValues="@array/fruit_options_values"
            android:key="@string/selected_fruit_option"
            android:summary="@string/listSummary"
            android:title="@string/listTitle" />

        <EditTextPreference
            android:dialogTitle="@string/customed_fruit_dialogTitle"
            android:key="@string/customed_fruit_pref"
            android:summary="@string/customed_fruit_summary"
            android:title="@string/customed_fruit_title" />
    </PreferenceCategory>

</PreferenceScreen>
注意:/res/xml/fruitoptions.xml文件还需要/res/values/strings.xml和/res/values/arrays.xml支持

想尽可能多的把所有preference都举例出,所以这个xml文件中包含了CheckBoxPreference,ListPreference,EditTextPreference,当然还有RingtonePreference没有举例出,留给读者自己研究。

CheckBoxPreference,ListPreference,EditTextPreference,三个东西都有很多属性android:key,android:title等,android:key有点像普通控件中的android:id。

其他ListPreference中的android:entries 是列表项要显示出的文本,android:entryValues是列表项的键或者值,其他属性都是描述性的,大家可以根据字面英文意思来理解。

需要注意的是这个布局文件中用到了PreferenceScreen和PreferenceCategory。

PreferenceScreen是一些配置的集合,会在一个独立的屏幕中显示,大家可以试一下嵌套的PreferenceScreen,点击后会弹出一个新的屏幕

PreferenceCategory 正如我们图1中显示的那样,会有一个独立的外框来分开。

2.接下来是 /res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="hello">Hello World, PreferenceDemoActivity!</string>
    <string name="app_name">PreferenceDemo</string>
    <string name="selected_fruit_option">selected_fruit_option</string>
    <string name="fruit_option_default_value">1</string>
    <string name="prefTitle">Preference 示例</string>
    <string name="listTitle">选择一个水果</string>
    <string name="dialogTitle">选择一个水果</string>
    <string name="listSummary"></string>
    <string name="btnText">点击打开配置</string>
    <string name="detailSetting">detailSetting</string>
    
    <string name="love_fruit_pref">like_fruit_pref</string>
    <string name="love_fruit_title">喜欢吃水果?</string>
    <string name="love_fruit_summary">喜欢吃水果的话就勾选此项:)</string>
    
    <string name="customed_fruit_pref">customed_fruit_pref</string>
    <string name="customed_fruit_title">你自己喜欢的水果?</string>
    <string name="customed_fruit_summary">上面的还不够,写下你喜欢的:)</string>
    <string name="customed_fruit_dialogTitle">我喜欢的水果</string>
</resources>


3.最后是/res/values/arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="fruit_options">
        <item>苹果</item>
        <item>葡萄</item>
        <item>橘子</item>
    </string-array>
    <string-array name="fruit_options_values">
        <item>0</item>
        <item>1</item>
        <item>2</item>
    </string-array>
</resources>


用@string/xxxx的方式来显示文字除了可以很容易的支持多种语言外还有很多好处,在获取key的时候也不需要打字符串,可以从strings.xml文件中读取,也不容易错。

4.好了到我们主Activity的布局代码了 /res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/btnOpenSetting"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/btnText" />
    <TextView 
        android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>


很简单,一个按钮,一个显示我们的结果。

Activity的代码部分 PreferenceDemoActivity.java

package com.waitingfy.android;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class PreferenceDemoActivity extends Activity {
	private Button btnOpenSetting;
	private TextView resutlTextView;
	private SharedPreferences prefs;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		/* 两种方式获得 SharedPreferences */
		// prefs = getSharedPreferences("com.waitingfy.android_preferences", 0);
		prefs = PreferenceManager
				.getDefaultSharedPreferences(getApplicationContext());
		btnOpenSetting = (Button) findViewById(R.id.btnOpenSetting);
		resutlTextView = (TextView) findViewById(R.id.result);
		// 按钮绑定点击监听
		btnOpenSetting.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				Intent intent = new Intent();
				intent.setClass(getApplicationContext(),
						com.waitingfy.android.FruitPreferenceActivity.class);
				startActivityForResult(intent, 0);
			}
		});
		setOptionText();
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		setOptionText();
	}

	/*
	 * 从首选项中获得值,给控件赋值
	 */
	private void setOptionText() {
		StringBuilder resultString = new StringBuilder();
		Resources resources = this.getResources();
		// 从checkboxPreference获得值
		Boolean isLove = prefs.getBoolean(
				resources.getString(R.string.love_fruit_pref), true);
		// 从listPreference获得值
		String selectFruit = prefs.getString(
				resources.getString(R.string.selected_fruit_option),
				resources.getString(R.string.fruit_option_default_value));
		// 从 EditTextPreference获得值
		String customedFruit = prefs.getString(
				resources.getString(R.string.customed_fruit_pref), "");
		resultString.append(isLove.toString() + ",");
		resultString.append(selectFruit + ",");
		resultString.append(customedFruit);
		resutlTextView.setText(resultString);
	}
}


都有注释,应该问题不大。

需要解析下的是有两种方法都可以得到SharedPreferences的实例

1. SharedPreferences prefs = getSharedPreferences("com.waitingfy.android_preferences", 0);

2. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

要从一个复选框首选项(CheckBoxPreference)中读取值用getBoolean()方法,将key传递给它就可以了,从ListPreference或EditPreference中读取值用getString(),也是传递一个key.

5.最后我们来看下载入首选项界面的代码是如何的FruitPreferenceActivity.java

通过这个代码我们就可以知道如何对首选项中的控件进行操作,不单单是读取他们的值。

package com.waitingfy.android;

import android.content.res.Resources;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;

public class FruitPreferenceActivity extends PreferenceActivity {
    private CheckBoxPreference checkBoxPreference;
    private PreferenceCategory preferenceCategory;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// 从资源中添加preferences
		addPreferencesFromResource(R.xml.fruitoptions);
		Resources resources = this.getResources();
		//使用findpreference根据key返回特定的preference
	    checkBoxPreference = (CheckBoxPreference) findPreference(resources
				.getString(R.string.love_fruit_pref));
	    preferenceCategory = (PreferenceCategory) findPreference(resources
				.getString(R.string.detailSetting));
	    //checkbox绑定点击事件
		checkBoxPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
			
			public boolean onPreferenceClick(Preference preference) {
				return SetPrefCategoryStateByCheckBoxState();
			}
		});
		SetPrefCategoryStateByCheckBoxState();
	}
	/*
	 * 根据checkbox的状态改变一个prefcategory的状态
	 * */
	private boolean SetPrefCategoryStateByCheckBoxState() {
		if(checkBoxPreference.isChecked()){
			preferenceCategory.setEnabled(true);
			return true;
		}else {
			preferenceCategory.setEnabled(false);
			return false;
		}
	}

}


代码也很清晰,主要是点击Checkboxpreference时我们要实现图1中下面两个选项的置灰效果,我们使用了findPreference,这个有点像findVIewById,只是这里传递进去的是key,不是Id,其他如Listpreference也可以通过findPreference来获取。

6.最后是我们的AndroidMinifest.xml文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.waitingfy.android"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".PreferenceDemoActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".FruitPreferenceActivity">
            <intent-filter>
                <action android:name="com.waitingfy.android.FruitPreferenceActivity"/>
                <category android:name="android.intent.category.PREFERENCE"/>
            </intent-filter>
        </activity>
    </application>

</manifest>


AndroidMinifest.xml中只要注册两个Activity就行了,第二个Activity有个category可以关注下

7. 最后来看下我们数据存储的位置:



在/data/data/应用程序包名称/shared_prefs下

里面的内容:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="selected_fruit_option">2</string>
<boolean name="like_fruit_pref" value="false" />
<string name="customed_fruit_pref">桃子</string>
</map>


好了,到这里这个Android首选项的示例就结束了,参考的是《精通Android2》的11章。

附上示例下载地址:PreferenceDemo

文章源地址 http://www.waitingfy.com/?p=9
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: