深入理解LauncherActvity
之LauncherActivity、PreferenceActivity、PreferenceFragment
从下图我们可以知道,LauncherActivity、PreferanceActivity均继承于ListActivity,其中LauncherActivity实现当列表界面列表项被点击时所对应的Acitvity被启动;PreferanceActivity实现一个程序参数设置、存储功能的Activity列表界面。
一、LauncherActivity使用详解
1.概述:LauncherActivity的作用是是开发一个列表界面Activity,但是这个列表界面与普通的列表界面有所不同。它开发出来的列表界面中的每个列表项都对应于一个Intent,通过重写Intent
intentForPosition(int position)方法根据不同列表返回不同的intent。当我们点击不同列表项时,应用程序会自动启动对应的Acitviy。效果如下:
2.LauncherActivity类介绍
(1)构造方法:LauncherActivity()
(2)重要方法
Intent intentForPosition(int position):根据不同列表返回不同的intent
void onCreate(Bundle savedInstanceState):启动Activity第一个被调用
void onListItemClick(ListView l, View v, int position, long id):当点击一个列表项时调用该方法
(3)Intent构造方法:用于实例化一个Intent对象
Intent()
Intent(Intent o)
Intent(String action)
Intent(String action, Uri uri)
Intent(Context packageContext, Class<?> cls)
Intent(String action, Uri uri, Context packageContext, Class<?> cls)
3.开发思路及源码
(1)为LauncherActivity界面填充列表项内容。通过装配适配器,将数组字符串数据源装配到视图,并根据按系统自带的android.R.layout.simple_expandable_list_item_1布局文件设计每个列表项外观和内容;
String[] names={"设置程序参数","查看人种"};
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1 , names);
setListAdapter(adapter);
(2)重写Intent intentForPosition(int
position)方法,实现根据不同列表返回不同的intent。当用户点击Activity列表项时,系统将传递该列表项所在的位置position参数给intentForPosition方法,最后返回一个intent给上下文界面从而实现启动相对应的Acitvity。
Class<?>[] classes={PreferenceActivityTest.class,ExpandableListActivityTest.class};
public Intent intentForPosition(int position)
{
return new Intent(LaunchActivity.this,classes[position]); //new一个intent
}
(3)实现intent对应的Acitvity,可以继承于Activity、PreferenceActivity、ExpandableListActivity等.
(3)源代码
package com.example.android_activity_1;
import android.app.LauncherActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ArrayAdapter;
/*主Activity:LauncherActivity
* 每个列表项都对应于一个Intent
* */
public class LaunchActivity extends LauncherActivity {
//1.定义两个Activity的名称
String[] names={"设置程序参数","查看人种"};
//2.定义两个Activity对应的实现类,前者用于显示一个显示设置选项参数并进行保存的窗口;后者用于显示一个可展开的列表窗口(Activity)
Class<?>[] classes={PreferenceActivityTest.class,ExpandableListActivityTest.class};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//3.装配ArrayAdapter适配器,将数据装配到对应的列表项视图中
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1 , names);
//4.设置该窗口显示的列表所需的adapter
setListAdapter(adapter);
}
//5.重写Intent IntentForPosition(int position)方法:根据列表项返回的intent,用于启动不同的Activity
public Intent intentForPosition(int position){
return new Intent(LaunchActivity.this,classes[position]); //返回一个Intent对象,已指明将要启动的类,其中 position的值在当用户点击Activity中列表项被确定
}
}
二、PreferenceActivity使用详解
1.概述:PreferenceActivity是一个非常有用的基类,当开发的Android应用程序需要进行选项设置并希望这些选项设置以参数的形式保存时,我们可以通过PreferenceActivity实现。PreferenceActivity与普通的Acitvity不同,它不再使用普通的界面布局文件,而是使用选项设置的布局文件。
选项设置的布局文件:以PreferenceScreen作为根元素,它表明定义一个参数设置的界面布局。
另外,一旦Activity继承了PreferenceActivity,那么该Activity完全不需要自己控制Preferences的读写,PreferenceActivity会为我们处理这一切。
2.PreferenceActivity类介绍
(1)嵌入类:class PreferenceActivity.Header
作用:用来描述用户将要点击的标头列表项
(2)PreferenceActivity重要方法
public void loadHeadersFromResource (int resid, List<PreferenceActivity.Header> target)
功能:解析resid所代表的布局资源文件,根据元素<header../>为一标头(列表项)添加到目标列表list中。
public void onBuildHeaders (List<PreferenceActivity.Header> target)
功能:负责加载页面布局文件到Activity,通过该方法添加加载至少一项标头到Activity列表中,并使acitvity运行在其fragment模式。其中,List<PreferenceActivity.Header>为一个列表集合用来存放布局文件中的标头,调用
loadHeadersFromResource(R.layout.*, List)方法将布局资源添加到列表list数据集中。
3.开发思路及源码
为了创建一个PreferenceActivity界面,首先需要创建一个对应的界面布局文件。从Android3.0开始,官方推荐将PreferenceActivity结合PreferenceFragment来实现参数设置界面。其中,PreferenceActivity只负责加载选项设置列表的布局文件(如图(A));PreferenceFragment才负责加载选项设置的布局文件(如图(B)).
(1)PreferenceActivity加载选项设置列表的布局文件,其根元素为<preference-headers
...>...</preference-headers>,每一列表项元素为<header
...></header>或者<intent.../>,具体效果如上图(A)所示。
<preference-headers ...>
//实现一个列表项
<header android:fragment="com.example.android_activity_1.PreferenceActivityTest$Prefs1Fragment"
//指定列表项启动Prefs1Fragment界面
android:icon="" //指定列表项图标
android:title="" //指定列表项的标题
android:summary=""> //指定列表项说明
<extra android:name="website"
//子元素<extra../>,给Prefs1Fragment界面(Activity)传递数据,即website="www.baidu.com"
android:value="www.baidu.com"/>
<intent
//子元素<intent.../>,启动一个Activity
</header>
................
</preference-headers>
其中,android:fragment的作用是指定列表项启动哪一个preferenceFragment界面,格式为:"包.类.$内部类",这个内部类继承于PreferenceFragment。在Prefs1Fragment 获取传入<extra.../>
该Fragment的参数 :
String website=getArguments().getString("website");
Toast.makeText(getActivity(), "网站域名是:"+website,
Toast.LENGTH_SHORT).show();
源代码res/layout/preference.xml:
该布局定义了三个列表项,其中前两个列表项通过android:fragment属性指定启动响应的PreferenceFragment;第三个列表项通过<intent../>子元素启动指定的Activity.
<?xml version="1.0" encoding="utf-8" ?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 指定:启动指定preferenceFragment的列表项 -->
<header android:fragment="com.example.android_activity_1.PreferenceActivityTest$Prefs1Fragment"
android:icon="@drawable/a"
android:title="背景灯光选项设置"
android:summary="设置sex的相关选项">
</header>
<!-- 指定:启动指定preferenceFragment的列表项 -->
<header android:fragment="com.example.android_activity_1.PreferenceActivityTest$Prefs2Fragment"
android:icon="@drawable/b"
android:title="人种选项设置"
android:summary="设置人种的相关选项">
<!-- 使用extra可向Activity传入额外的数据 -->
<extra android:name="website"
android:value="www.baidu.com"/>
</header>
<header
android:icon="@drawable/c"
android:title="使用Intent"
android:summary="使用Intent启动某个Activity">
<intent
android:action="android.intent.action.VIEW"
android:data="http://www.baidu.com"/>
</header>
</preference-headers>
(2)实现一个继承于PreferenceActivity的Activity(PreferenceActivityTest.java),主要完成两个任务:
a.加载指定的选项设置列表布局文件(res/layout/preference.xml)到PreferenceActivity,通过重写其public
void onBuildHeaders(List<Header> target)方法实现;
public void onBuildHeaders(List<Header>
target)
{
super.loadHeadersFromResource(R.layout.preference,
target);
}
b.定义实现选项设置列表的布局文件中使用的PreferenceFragment内部类;
public static class Prefs1Fragment extends PreferenceFragment
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
//加载选项设置布局文件到PreferenceFragment
}
}
源代码src/包名/PreferenceActivityTest.java:
package com.example.android_activity_1;
import java.util.List;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.widget.Button;
import android.widget.Toast;
/*PreferenceActivity:
* 结合PreferenceFragment实现参数设置界面,
* 其中,PreferenceFragment负责加载选项设置的布局文件;PreferenceActivity负责加载选项设置列表的布局文件*/
public class PreferenceActivityTest extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//1.该方法用于为该界面设置一个标题按钮
if(hasHeaders())
{
Button button=new Button(this);
button.setText("设置操作");
//将该按钮添加到该界面上
setListFooter(button);
}
}
//2.该方法加载选项列表的页面布局文件
@Override
public void onBuildHeaders(List<Header> target) {
// TODO Auto-generated method stub
super.loadHeadersFromResource(R.layout.preference, target);
}
//3.在PreferenceActivityTest中显示Prefs1Fragment、Prefs2Fragment两个内部类
public static class Prefs1Fragment extends PreferenceFragment
{
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences); //加载选项设置布局文件到PreferenceFragment
}
}
public static class Prefs2Fragment extends PreferenceFragment
{
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.display_prefs); //加载选项设置布局文件到PreferenceFragment
//获取传入该Fragment的参数
String website=getArguments().getString("website");
Toast.makeText(getActivity(), "网站域名是:"+website, Toast.LENGTH_SHORT).show();
}
}
}
(3)建立选项设置参数布局文件display_prefs.xml、preferences.xml
选项设置参数布局文件,以<PreferenceScreen....></PreferenceScreen>为根元素。选项参数的每一项,我们可以通过系统提供的属性来构造自己的选项设置参数组,实现预期的功能。
源代码res/xml/preferences.xml
<?xml version="1.0" encoding="utf-8" ?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title='"背景灯光组"'>
<ListPreference //说明:该参数选项为列表框输入参数
android:key="light"
android:title="灯光强度" //参数选项标题
android:summary="请选择灯光强度(测试ListPreference)" //参数选项二级标题
android:dialogTitle="请选择灯光强度" //弹出列表框的标题
android:entries="@array/light_strength_list" //列表框将要显示的内容
android:entryValues="@array/light_value_list"/>
</PreferenceCategory>
<PreferenceCategory android:title="文字显示组">
<SwitchPreference
android:key="autoScroll"
android:title="自动滚屏"
android:summaryOff="自动滚屏:关闭"
android:summaryOn="自动滚屏:开启"
android:defaultValue="true"/>
</PreferenceCategory>
</PreferenceScreen>
源代码res/xml/display_prefs.xml
<?xml version="1.0" encoding="utf-8" ?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<RingtonePreference
android:key="ring_key"
android:title="设置铃声"
android:showSilent="true"
android:ringtoneType="all"
android:showDefault="true"
android:summary="选择铃声(测试RingtonePreference)"/>
<PreferenceCategory android:title="个人信息设置组">
<EditTextPreference
android:summary="填写你的用户名(测试EditTextPreference)"
android:key="name"
android:dialogTitle="您所使用的用户名为:"
android:title="填写用户名"/>
<ListPreference
android:summary="选择您的性别(测试ListPreference)"
android:key="gender"
android:entries="@array/gender_name_list"
android:dialogTitle="ListPreference"
android:title="性别"
android:entryValues="@array/gender_value_list"/>
</PreferenceCategory>
<PreferenceCategory android:title="系统功能设置组">
<CheckBoxPreference
android:summaryOff="自动保存:关闭"
android:title="自动保存进度"
android:summaryOn="自动保存:开启"
android:key="autoSave" android:defaultValue="true"/>
</PreferenceCategory>
</PreferenceScreen>
说明:上面的界面布局文件定义了一个参数设置界面,该参数设置界面中包括两个参数设置组。一旦定义了参数设置的界面布局文件,我们再在PreferenceFragment中调用 addPreferencesFromResource(R.xml.preferences);方法加载选项设置布局文件到PreferenceFragment。
(1)android:key属性:
(2)res/values/array/数组
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="light_strength_list" >
<item >暗</item>
<item >亮</item>
<item >最亮</item>
</string-array>
<string-array name="light_value_list" >
<item >1</item>
<item >2</item>
<item >3</item>
</string-array>
</resources>
(4)修改工程文件AndroidManifest.xml配置、管理上面的三个Activity。即在清单文件的<application.../>元素中增加ExpandableListActivityTest和PreferenceActivityTest界面Activity。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android_activity_1"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="14" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".LaunchActivity"
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=".ExpandableListActivityTest"
android:label="查看人种" >
</activity>
<activity
android:name=".PreferenceActivityTest"
android:label="设置选项参数" >
</activity>
</application>
</manifest>
总结:上述应用通过PreferenceActivity生成选项设置列表界面;PreferenceFragment生成选项设置界面(如图(B))。使用PreferenceActivity来进行应用程序选项参数的设置,系统会自动将设置的参数永久的保存到系统中。例如,我们单击设置选项中的"填写用户名"列表项,程序将会自动保存设置的选项参数到手机/data/data/<应用程序包名>/share_prefs路径下,文件名为<应用程序包名>_preferences.xml。
三、PreferenceFragment详解
在android的应用中通常都有setting功能,能够设置一些全局的选项,例如字体颜色,个人喜好等等。 这些东西都是存在一个xml中的,在android中对应的对象就是SharedPreferences。
PreferenceFragment 还是 PreferenceActivity
很明显PreferenceFragment 是Fregment, PreferenceActivity是Activity。
当你的应用针对的系统在3.0以上的时候,你就应该用PreferenceFragment,现在主流系统4.0的情况下,当然选择使用PreferenceFragment。原因是PreferenceFragment是一个更加平滑的结构,你可以将它依附在任何的activity上面,谷歌强力推荐使用PreferenceFragment!
常用Preference
CheckPreference —— CheckBox 单选框
EditTextPreference —— EditText 输入文本框
ListPreference —— ListView 列表框
RingtonePreference —— 选择铃声
XML定义常用的属性有:
android:key : 每个Preference控件独一无二的”ID”,唯一表示此Preference。
android:defaultValue : 默认值。 例如,CheckPreference的默认值可为”true”,默认为选中状态;
EditTextPreference的默认值可为”110” 。
android:enabled : 表示该Preference是否可用状态。
android:title : 每个Preference在PreferenceScreen布局上显示的标题——大标题
android:summary : 每个Preference在PreferenceScreen布局上显示的标题——小标题(可以没有)
ListPreference中:
android:entries:类型为array,控件欲显示的文本
android:entryValues:类型为array,与文本相对应的key-value键值对,value保存至sharedPreference文件
PreferenceFragment 使用步骤(方法二)
1.定义preference在项目的res/xml中新建一个preferences.xml.用于定义菜单界面的设置选项
(其中,android:entries 和 android:entryValues 定义在res/values/strings.xml中)
2.创建一个activity用于给PreferenceFragment
依附
- package com.example.androidpreferencefragment;
-
- import android.app.Activity;
- import android.os.Bundle;
-
- public class SetPreferenceActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
-
- getFragmentManager().beginTransaction().replace(android.R.id.content,
- new PrefsFragment()).commit();
- }
-
- }
3. 创建PreferenceFragment。
implements
OnSharedPreferenceChangeListener 是用于监听SharedPreference是否改变的。这里主要的作用是当SharedPreference改变的时候及时更新界面中preference的summary,提供一个更好的交互。注意在OnResume和OnPause中要注册和卸载监听器,维护activity中的生命周期。注:不能给每个preference设置OnChangeListener来更新界面中preference的summary,这样会阻止系统存储preference.xml.
- package com.example.androidpreferencefragment;
-
- import android.annotation.SuppressLint;
- import android.content.SharedPreferences;
- import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
- import android.os.Bundle;
- import android.preference.Preference;
- import android.preference.PreferenceFragment;
- import android.preference.Preference.OnPreferenceChangeListener;
-
- @SuppressLint("NewApi")
- public class PrefsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener{
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
-
- // Load the preferences from an XML resource
- addPreferencesFromResource(R.xml.preferences);
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- // TODO Auto-generated method stub
- // Set summary to be the user-description for the selected value
- if(!key.equals(MainActivity.PRF_CHECK))
- {
- Preference connectionPref = findPreference(key);
- connectionPref.setSummary(sharedPreferences.getString(key, ""));
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
-
- }
-
- @Override
- public void onPause() {
- getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
- super.onPause();
- }
-
- }
4.设置默认
当用户第一次运行应用的时候,用户还没有设置自己preference,这时候就要指定默认的prefernnce了。
首先在xml定义好android:defaultValue项。然后在主Activity(也可以是其他activity,但在第一次运行的时候一定会进去,比如闪屏Activity)的onCreate方法中调用setDefaultValues方法。
- PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
这个函数有三个参数:
第一个为应用上下文,第二个是preference的id,第三个为false指只在第一次运行的时候加载默认值。
5.取出preference值
SharedPreferences mySharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
然后通过get方法和key值就可以取出对应的值了,比如:
boolean my_checkbox_preference = mySharedPreferences.getBoolean("checkbox_preference", false);
String my_edittext_preference = mySharedPreferences.getString("edittext_preference", "");
参考: