PreferenceActivity参数设置界面
对于PreferenceActivity的认识和应用,在应用中出现需要设置应用参数的时候,个人觉得第一想到的是PreferenceActivity
因为preferenceActivity完全不需要我们进行数据的读写。
它跟普通的Activity不一样,因为他不使用普通的界面的布局文件,而是使用选项设置的布局文件。(这带来一个问题:
让我们很难对界面进行优美的设置,很难随心所欲)选项设置的布局文件以PreferenceScreen作为根元素---它表明定义一个参数设置的界面布局
现在都流行PreferenceActivity与PreferenceFragment结合使用,其中前者负责加载选项设置列表的布局文件,后者才负责加载选项设置的布局文件
PreferenceActivity加载选项设置列表的布局文件:<preference-headers 作为根元素 其中包含若干以<header作为根元素的选项设置的布局文件
<header
android:fragment="" 使用PreferenceFragment加载选项设置的类
android:icon="" 图标
android:title=""标题
android:summary=""描述
作为一名优秀的程序猿,应该时常去看看源代码,(Ctrl+鼠标左键)
寻找 Preference Headers 的布局方式:
Headers 是在 PreferenceActivity 中进行布局的,PreferenceActivity 其实是继承了一个 ListActivity,所以呈现在我们面前的 Headers 列表其实就是一个 ListView,那么我们很自然地想到每个 Header ,即每个 list item 的布局应该在一个 ListA dapter 中被 inflated ,查看 PreferenceActivity 的源代码,发现里面定义了一个 ArrayAdapter<Header> 的子类 HeaderAdapter,请注意 getView 中是如何 inflate header item 布局的:
Headers 是在 PreferenceActivity 中进行布局的,PreferenceActivity 其实是继承了一个 ListActivity,所以呈现在我们面前的 Headers 列表其实就是一个 ListView,那么我们很自然地想到每个 Header ,即每个 list item 的布局应该在一个 ListA dapter 中被 inflated ,查看 PreferenceActivity 的源代码,发现里面定义了一个 ArrayAdapter<Header> 的子类 HeaderAdapter,请注意 getView 中是如何 inflate header item 布局的:
@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;
}
}
分析 header item 布局文件 preference_header_item.xml :
从 getView 方法中我们确认了 header item 的布局在 preference_header_item.xml 这个文件中,那么要更改布局方式其实就是修改这个文件,我们从源码的资源文件中找到该文件的 源代码,发现每一个 header item 都由 icon(ImageView)、title(TextView) 和 summary(TextView) 三个元素组成。接下来就可以考虑如何对其进行修改了。
如何修改 preference_header_item.xml?
这里我们不打算对 header 进行复杂的自定义(比如,增加额外的 header 元素,这个需要对 Header 本身也进行定制,考虑到 Header 的简洁要求,个人觉得没有必要这么做)。
在本文中,我们实现一些比较有用的自定义,具体来说包括如下修改: icon 和 title、summary 位置的互换,title 和 summary 字体颜色、大小的更改,list item 高度的修改,list item 背景的修改(修改 selector),正如上图给出的效果所示。
定义一个本地布局文件 custom_preference_header_item.xml:
我们将原生的 preference_header_item.xml 文件拷贝到本地工程 layout 文件夹中,修改文件名称为 custom_preference_header_item.xml,并对布局进行 3.3 中所述的修改。
定义一个 PreferenceActivity 的子类 CustomPreferenceActivity:
在 CustomPreferenceActivity 中重新定义一个 HeaderAdapter,主要将其中的
view = mInflater.inflate(mLayoutResId, parent, false);
改成
<span style="white-space:pre"> </span>view = mInflater.inflate(R.layout.custom_preference_header_item,
parent, false);
由于 PreferenceActivity 中的 List<Header> 成员 target 是私有的,而我们要将 target 作为数据源参数传递给新定义的 HeaderAdapter 中,为了解决这个问题,我们在 CustomPreferenceActivity 中再定义一个 List<Header> 成员 mCopyHeaders,作为 target 的一个拷贝,并通过重写 loadHeadersFromResource 方法将 targets 赋值给 mCopyHeaders:
public void loadHeadersFromResource(int resid, List<Header> target) {
super.loadHeadersFromResource(resid, target);
mCopyHeaders = target;
}
在 PreferenceActivity 源码 中,setListAdapter() 是在 onCreate() 方法中调用的,为此,我们还要重写 onCreate() 方法,将 CustomPreferenceActivity 中的 adapter 设置为自定义的 HeaderAdapter 对象:protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mCopyHeaders != null && mCopyHeaders.size() > 0) {
setListAdapter(new HeaderAdapter(this, mCopyHeaders));
}
}
至此,Preference Header 的自定义布局就完成了,接下来就只需要定义一个 CutomPreferenceActivity 的子类,并编写相应的 preference-headers 文件,重新 onBuildHeaders() 方法就可以了:
public void onBuildHeaders(List<Header> target) {
this.loadHeadersFromResource(R.xml.preference_headers, target);
}
<header
android:icon="@drawable/ic_settings_display"
android:title="使用Intent"
android:summary="使用Intent启动Activity">
<intent
android:action="android.intent.action.VIEW"
android:data="http://www.baidu.com"/>
</header>
在使用intent 打开网站时 在android:data=" 网址" 要加上http://或https://
时间:2016年7月20日17:03:57 文章添加:
大家注意到该图与上面那图的区别了吗 。设置列表前面添加了一个图片和一个表题 ,这是怎么实现的呢?我来告诉你们:
1.:先创建一个布局文件,
注意几点: (1) 其中<ListVIew>就是代表你的设置列表,你可以在他的前面或者后添加文本、图片、按钮等等。
(2)有人会问可不可以用其他布局,我想说随你怎么用。
(3)一定 一定 一定要包含<ListVIew>(重要事情说三遍)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:src="@drawable/tools"
android:layout_width="60dp"
android:layout_height="60dp" />
<TextView android:text="设置"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<ListView
android:layout_width="fill_parent"
android:id="@android:id/list"
android:layout_height="fill_parent">
</ListView>
</LinearLayout>
布局文件写好了后就应该在程序代码中引用
public class PreferenceActivityTest extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (hasHeaders())
{
Button bt = new Button(this);
bt.setText("设置操作");
setListFooter(bt);
}
// setContentView(R.layout.activity_main); 1
}
@Override
public void onBuildHeaders(List<Header> target) {
super.onBuildHeaders(target);
loadHeadersFromResource(R.xml.preference_headers,target);
setContentView(R.layout.activity_main); 2
}
还是使用setContentView进行布局文件调用,认真看的应该都看到我在onCreate中和onBuildHeader中调用了setContentVIew()
在我的经验来说 在onCreate中调用会出现错误,在onBuildHeaders中不会出现。
今天就到这里。