asp网站开发的开发环境,深圳生产型企业网站建设专业,安装网络要多少钱,设置网址之前发过一篇有关于自定义preference 在ActivityGroup 的包容下出现UI不能更新的问题#xff0c;当时还以为是Android 的一个BUG 现在想想真可笑 。其实是自己对机制的理解不够深刻#xff0c;看来以后要多看看源码才行。本篇讲述内容大致为如何自定义preference 开始到与Act…之前发过一篇有关于自定义preference 在ActivityGroup 的包容下出现UI不能更新的问题当时还以为是Android 的一个BUG 现在想想真可笑 。其实是自己对机制的理解不够深刻看来以后要多看看源码才行。本篇讲述内容大致为如何自定义preference 开始到与ActivityGroup 互用下UI更新的解决方法。首先从扩展preference开始类文件必须继承自Preference并实现构造函数这里我一般实现两个构造函数分别如下(类名为test)publictest(Context context) {this(context,null);//TODO Auto-generated constructor stub}publictest(Context context, AttributeSet attrs) {super(context, attrs);//TODO Auto-generated constructor stub}这里第二个构造函数第二个参数为可以使用attrs 为我们自定义的preference 添加扩展的注册属性比如我们如果希望为扩展的preference 添加一个数组引用就可使用如下代码intresouceIdattrs.getAttributeResourceValue(null,Entries,0);if(resouceId0) {mEntriesgetContext().getResources().getTextArray(resouceId);}这里的mEntries 是头部声明的一个数组我们可以在xml文件通过 Entries数组索引得到一个数组。在这里不深入为大家示范了。我们扩展preference 有时想让其UI更丰富更好看这里我们可以通过引用一个layout 文件为其指定UI可以通过实现如下两个回调函数OverrideprotectedView onCreateView(ViewGroup parent) {//TODO Auto-generated method stubreturnLayoutInflater.from(getContext()).inflate(R.layout.preference_screen, parent,false);}此回调函数与onBindView 一一对应并优先执行于onBindView 当创建完后将得到的VIEW返回出去给onBindView处理如下代码OverrideprotectedvoidonBindView(View view) {//TODO Auto-generated method stubsuper.onBindView(view);canlendarCalendar.getInstance();layout(RelativeLayout) view.findViewById(R.id.area);title(TextView) view.findViewById(R.id.title);summary(TextView) view.findViewById(R.id.summary);layout.setOnClickListener(this);title.setText(getTitle());summary.setText(getPersistedString(canlendar.get(Calendar.YEAR)/(canlendar.get(Calendar.MONTH)1)/canlendar.get(Calendar.DAY_OF_MONTH)));}TiponBindView 不是必须的可以将onBindView 里的处理代码在onCreateView 回调函数一并完成然后返回给onBindView 具体怎么写看自己的代码风格吧。我个人比较喜欢这种写法比较明了。下面我们来了解一下我扩展preference 比较常用到的几个方法Preference another)与另外一个preference比较如果相等则返回0不相等则返回小于0的数字。Object newValue)如果你希望你扩展的Preference 可以支持当数值改变时候可以调用OnPreferenceChangeListener此监听方法则必须调用此方法查看该方法源码为protectedboolean callChangeListener(Object newValue) {returnmOnChangeListenernull?true: mOnChangeListener.onPreferenceChange(this, newValue);}源码简单不做过多介绍只是实现一个接口。protectedboolean getPersistedBoolean(boolean defaultReturnValue) {if(!shouldPersist()) {returndefaultReturnValue;}returnmPreferenceManager.getSharedPreferences().getBoolean(mKey, defaultReturnValue);}如果你有接触过sharePreference 相信一眼就能看出这里它为我们做了什么。如上获取一个String 数值protectedboolean persistBoolean(boolean value) {if(shouldPersist()) {if(valuegetPersistedBoolean(!value)) {//Its already there, so the same as persistingreturntrue;}SharedPreferences.Editor editormPreferenceManager.getEditor();editor.putBoolean(mKey, value);tryCommit(editor);returntrue;}returnfalse;}都是sharePreference 的知识这里不做过多介绍。其他的跟上面的都 一样略过。通过如上的一些设置一个基本的扩展preference 就己经完成下面来讲讲如果在ActivityGroup 里面让扩展的preference可以更新UI。之前 农民伯伯 探讨过他建议我使用onContentChanged()方法可以使UI更新 试了一下发现有些许问题不过非常感谢农民伯伯。这个方法是全局刷新则全部UI都刷新一次但是这样不是很合理我想了一下那既然此方法可以更新UI那么一定可以行得通我查看一下源码下面把源码贴出来OverridepublicvoidonContentChanged() {super.onContentChanged();postBindPreferences();}/*** Posts a message to bind the preferences to the list view.* * Binding late is preferred as any custom preference types created in* {link #onCreate(Bundle)} are able to have their views recycled.*/privatevoidpostBindPreferences() {if(mHandler.hasMessages(MSG_BIND_PREFERENCES))return;mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();}privatevoidbindPreferences() {final PreferenceScreen preferenceScreengetPreferenceScreen();if(preferenceScreen!null) {preferenceScreen.bind(getListView());}}privatestaticfinalintMSG_BIND_PREFERENCES0;privateHandler mHandlernewHandler() {OverridepublicvoidhandleMessage(Message msg) {switch(msg.what) {caseMSG_BIND_PREFERENCES:bindPreferences();break;}}};原来这里它是另开一条线程来更新UI然后当值发生变化时为其发送消息在消息队列里面处理UI只不过它这里继承了listActivity 更新了一整个listView 那么我们就将它提取出来只更新我们想要的UI则可。OK思路出来了下面将我扩展的一个preference 的源码提供出来package com.yaomei.preference;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import android.app.Dialog;import android.content.Context;import android.content.DialogInterface;import android.os.Handler;import android.os.Message;import android.preference.Preference;import android.preference.PreferenceGroup;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.View.OnClickListener;import android.widget.AdapterView;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.SimpleAdapter;import android.widget.TextView;import android.widget.AdapterView.OnItemClickListener;import com.yaomei.set.R;publicclassPreferenceScreenExt extends PreferenceGroup implementsOnItemClickListener, DialogInterface.OnDismissListener {privateDialog dialog;privateTextView title, summary;privateRelativeLayout area;privateListView listView;Listlist;privateListlistStr;privateCharSequence[] mEntries;privateString mValue;privateSimpleAdapter simple;privatestaticfinalintMSG_BIND_PREFERENCES0;privateHandler mHandlernewHandler() {OverridepublicvoidhandleMessage(Message msg) {switch(msg.what) {caseMSG_BIND_PREFERENCES:setValue(mValue);break;}}};publicPreferenceScreenExt(Context context, AttributeSet attrs) {this(context, attrs, android.R.attr.preferenceScreenStyle);//TODO Auto-generated constructor stub}publicPreferenceScreenExt(Context context, AttributeSet attrs,intdefStyle) {super(context, attrs, android.R.attr.preferenceScreenStyle);//TODO Auto-generated constructor stubintresouceIdattrs.getAttributeResourceValue(null,Entries,0);if(resouceId0) {mEntriesgetContext().getResources().getTextArray(resouceId);}}OverrideprotectedvoidonBindView(View view) {//TODO Auto-generated method stubarea(RelativeLayout) view.findViewById(R.id.area);title(TextView) view.findViewById(R.id.title);summary(TextView) view.findViewById(R.id.summary);title.setText(getTitle());summary.setText(getPersistedString(getSummary().toString()));area.setOnClickListener(newOnClickListener() {OverridepublicvoidonClick(View v) {//TODO Auto-generated method stubshowDialog();}});}OverrideprotectedView onCreateView(ViewGroup parent) {//TODO Auto-generated method stuView viewLayoutInflater.from(getContext()).inflate(R.layout.preference_screen, parent,false);returnview;}publicvoidbindView(ListView listview) {intlengthmEntries.length;inti0;listStrnewArrayList();for(i0; iHashMapmapnewHashMap();map.put(keyname, mEntries[i].toString());listStr.add(map);}simplenewSimpleAdapter(getContext(), listStr, R.layout.dialog_view,newString[] {keyname},newint[] { R.id.text });listview.setAdapter(simple);listview.setOnItemClickListener(this);}publicvoidshowDialog() {listViewnewListView(getContext());bindView(listView);dialognewDialog(getContext(), android.R.style.Theme_NoTitleBar);dialog.setContentView(listView);dialog.setOnDismissListener(this);dialog.show();}OverridepublicvoidonItemClick(AdapterViewparent, View view,intposition,longid) {//TODO Auto-generated method stubmValuelistStr.get(position).get(keyname).toString();persistString(mValue);callChangeListener(mValue);dialog.dismiss();}OverridepublicvoidonDismiss(DialogInterface dialog) {//TODO Auto-generated method stub}privateOnPreferenceChangeListener temp;publicinterfaceOnPreferenceChangeListener {publicboolean onPreferenceChange(Preference preference, Object newValue);}publicvoidsetOnPreferenceChangeListener(OnPreferenceChangeListener preference) {this.temppreference;}publicvoidsetValue(String value) {summary.setText(value);}publicboolean callChangeListener(Object newValue) {returntempnull?true: temp.onPreferenceChange(this, newValue);}publicvoidpostBindPreferences() {if(mHandler.hasMessages(MSG_BIND_PREFERENCES))return;mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();}}然后在preferenceActivity 界面在回调函数onPreferenceChange调用postBindPreferences即可更新。Tip:这里的onPreferenceChange 调用postBindPreferences 不是必须的你同样可以在内部里面实现通过执行某一操作发送消息也可。好了在这里我要感谢那几位朋友对我的帮助提出了很多宝贵的意见。谢谢。