标签:
如上描述可用示意图标示:
在介绍它的使用方法之前,为了更好的理解PreferenceActivity,我会先对源码做一个简单的分析,分析结束后再介绍它的用法,包括显示Header和显示preference,这样更容易理解为什么会这么使用。
可以看到PreferenceActivity继承自ListActivity,而ListActivity是一个封装了ListView的Activity,在ListActivity中给ListView设置了事件监听器:
mList.setOnItemClickListener(mOnClickListener);
private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { onListItemClick((ListView)parent, v, position, id); } };
protected void onListItemClick(ListView l, View v, int position, long id) { }它是一个空的方法,如果你的Activity继承自ListActivity,想处理ListView的事件的话,只需要重写这个方法。
ListActivity中提供了给ListView设置适配器的接口,但是适配器还得自己去写,因此可以说ListActivity功能有限。PreferenceActivity继承了ListActivity,那么它当然主要是一个ListView了,那么它会怎样给ListView设置适配器呢?它又怎样处理按键事件?
Header是PreferenceActivity一个非常重要的概念,PreferenceActivity可以显示一系列的Header,每一个Header可以给它关联一个fragment,这样当你点击这个Header时,就会打开它关联的fragment,但是不局限于此,从源码来看,如果没有关联Fragment,那么也可以设置Intent,此时,可以通过Intent打开对应的Activity。
这个类还有两种模式,singlepane和two panes,分别针对小屏幕设备和大屏幕设备。对小屏幕设备而言,屏幕只会显示header,而大屏则会同时显示它关联的frament。
Header是一个定义在PreferenceActivity中的内部类:
public static final class Header implements Parcelable {它实现了Parcelable接口,表明它可以被序列化。它无非就是一个容器,里面保存了一个条目的所有相关的内容,比如这个条目的title-标题,summary-描述,fragment-关联的fragment等等。当我们要显示它的时候,我们只需要构造好Header,然后把它提交给PreferenceActivity就可以了,提交的方法是重写onBuildHeaders方法,这个方法的参数是一个List<Header >,只需要把自己构造的Header添加到这个List就可以了。此外,还需要覆写isValidFragment方法,后面会有介绍。
setListAdapter(new HeaderAdapter(this, mHeaders, mPreferenceHeaderItemResId, mPreferenceHeaderRemoveEmptyIcon));
private static class HeaderAdapter extends ArrayAdapter<Header> { private static class HeaderViewHolder { ImageView icon; TextView title; TextView summary; } private LayoutInflater mInflater; private int mLayoutResId; private boolean mRemoveIconIfEmpty; public HeaderAdapter(Context context, List<Header> objects, int layoutResId, boolean removeIconBehavior) { super(context, 0, objects); mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mLayoutResId = layoutResId; mRemoveIconIfEmpty = removeIconBehavior; } @Override public View getView(int position, View convertView, ViewGroup parent) { HeaderViewHolder holder; View view; if (convertView == null) { view = mInflater.inflate(mLayoutResId, parent, false); holder = new HeaderViewHolder(); holder.icon = (ImageView) view.findViewById(com.android.internal.R.id.icon); holder.title = (TextView) view.findViewById(com.android.internal.R.id.title); holder.summary = (TextView) view.findViewById(com.android.internal.R.id.summary); view.setTag(holder); } else { view = convertView; holder = (HeaderViewHolder) view.getTag(); } // All view fields must be updated every time, because the view may be recycled Header header = getItem(position); if (mRemoveIconIfEmpty) { if (header.iconRes == 0) { holder.icon.setVisibility(View.GONE); } else { holder.icon.setVisibility(View.VISIBLE); holder.icon.setImageResource(header.iconRes); } } else { holder.icon.setImageResource(header.iconRes); } holder.title.setText(header.getTitle(getContext().getResources())); CharSequence summary = header.getSummary(getContext().getResources()); if (!TextUtils.isEmpty(summary)) { holder.summary.setVisibility(View.VISIBLE); holder.summary.setText(summary); } else { holder.summary.setVisibility(View.GONE); } return view; } }
从定义中可以看到,HeaderAdapter是一个ArrayAdapter的子类,并且复写了getView方法。在getView方法中,根据header中的内容,填充icon,title.summary等。
@Override protected void onListItemClick(ListView l, View v, int position, long id) { if (!isResumed()) { return; } super.onListItemClick(l, v, position, id); if (mAdapter != null) { Object item = mAdapter.getItem(position); if (item instanceof Header) onHeaderClick((Header) item, position); } }可以看到它重写了onListItemClick方法,用于处理事件,在这个方法中调用了onHeaderClick方法:
public void onHeaderClick(Header header, int position) { if (header.fragment != null) { if (mSinglePane) { int titleRes = header.breadCrumbTitleRes; int shortTitleRes = header.breadCrumbShortTitleRes; if (titleRes == 0) { titleRes = header.titleRes; shortTitleRes = 0; } startWithFragment(header.fragment, header.fragmentArguments, null, 0, titleRes, shortTitleRes); } else { switchToHeader(header); } } else if (header.intent != null) { startActivity(header.intent); } }
关于Header的显示,我们可以自定义适配器,这时候需要重写setListAdapter方法,比如:
@Override public void setListAdapter(ListAdapter adapter) { if (adapter == null) { super.setListAdapter(null); } else { } }这个方法是ListActivity中提供的用于设置适配器的方法,这个方法在PreferenceActivity的onCreate方法中调用,用来给ListView设置适配器。
@Override public void onBuildHeaders(List<Header> headers) { }这个方法在PreferenceActivity的onCreate方法中调用。它的调用在setListAdapter之前,用来构造Header。
写一个Activity,继承PreferenceActivity,然后覆写onBuildHeaders方法即可:
public class MainActivity extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); } @Override public void onBuildHeaders(List<Header> target) { for(int i=0;i<5;i++){ Header header = new Header(); header.title = "hello"+i; header.summary = "hehe"+i; header.extras = new Bundle(); header.fragment = MyFrament.class.getName(); target.add(header); } super.onBuildHeaders(target); } }
1.setContentView要注释掉,因为如果重新设置ContentView,那么ListActivity中设置的ListView就找不到了。
2.onBuildHeaders中,构造的header要添加到target列表中。
3.fragment一定要设置,不设置就不会显示的,因此你需要自己实现一个与Header关联的Fragment,这个Fragment会在点击Header的时候被打开。
4.因为PreferenceActivity中已经提供了默认的适配器,所以,如果不需要自定义,则不需重写setListAdapter方法。
这样只是单纯的可以显示一些Header,但是点击Header还是会报错,我们还必须要覆写一个方法:
@Override protected boolean isValidFragment(String fragmentName) { return true; }
即明确告诉PrefercenceActivity我们准备了一个合法的Fragment。
在Fragment中可以显示preference了,这里暂时什么都不显示,这样打开的是一个空页面:
public class MyFrament extends PreferenceFragment { public void onCreate(Bundle b) { super.onCreate(b); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return null; } }代码效果如下:
XML构造Header更加简单方便。
2.1构建xml文件:
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> <header android:fragment="com.konka.preferenceactivitytest1.MyFrament" android:icon="@mipmap/ic_launcher" android:title="Prefs 1" android:summary="An example of some preferences." /> <header android:fragment="com.konka.preferenceactivitytest1.MyFrament" android:icon="@mipmap/ic_launcher" android:title="Prefs 2" android:summary="Some other preferences you can see."> <!-- Arbitrary key/value pairs can be included with a header as arguments to its fragment. --> <extra android:name="someKey" android:value="someHeaderValue" /> </header> <header android:icon="@mipmap/ic_launcher" android:title="Intent" android:summary="Launches an Intent."> <intent android:action="android.intent.action.VIEW" android:data="http://www.baidu.com" /> </header> </preference-headers>2.2加载XML文件:
public void onBuildHeaders(List<Header> target) { // for(int i=0;i<5;i++){ // Header header = new Header(); // header.title = "hello"+i; // header.summary = "hehe"+i; // header.fragment = MyFrament.class.getName(); // target.add(header); // } // super.onBuildHeaders(target); loadHeadersFromResource(R.xml.preference_header, target); }
PreferenceActivity除了可以显示Header和它关联的fragment之外,还可以直接显示preference,这些prefercence可以直接从XML文件中加载。PreferenceActivity显示preference的Api大都可以在PreferenceFragment中找到,而且更推荐使用PreferenceFragment来显示preference,不过在很多比较旧的的代码中,还保留着很多使用PreferenceActivity显示preference的代码。
使用PreferenceActivity显示preference只需要两步:
3.1在xml文件下创建xml配置文件:
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <Preference android:icon="@drawable/ic_settings_wifi_4" android:key="network" android:title="@string/connectivity_network" > <intent android:targetClass="com.android.tv.settings.connectivity.NetworkActivity" android:targetPackage="com.android.tv.settings" /> </Preference> <Preference android:icon="@drawable/ic_settings_cast" android:key="cast" android:title="@string/system_cast" > <intent android:action="com.google.android.settings.CAST_RECEIVER_SETTINGS" /> </Preference> <Preference android:icon="@drawable/ic_settings_apps" android:key="apps" android:title="@string/device_apps" > <intent android:targetClass="com.android.tv.settings.device.apps.AppsActivity" android:targetPackage="com.android.tv.settings" /> </Preference> <Preference android:icon="@drawable/ic_settings_storage" android:key="storagereset" android:title="@string/device_storage_reset" > <intent android:targetClass="com.android.tv.settings.device.StorageResetActivity" android:targetPackage="com.android.tv.settings" /> </Preference> <Preference android:icon="@drawable/ic_settings_about" android:key="about_device" android:title="@string/about_preference"> <intent android:targetClass="com.android.tv.settings.about.AboutActivity" android:targetPackage="com.android.tv.settings" /> </Preference> </PreferenceScreen>
3.2在代码中加载XML文件
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); addPreferencesFromResource(R.xml.item); }这样两步就可以构造一个设置界面了。
标签:
原文地址:http://blog.csdn.net/u011913612/article/details/51970765