android自定义更新,Android 完美解决自定义preference与ActivityGroup UI更新的问题
之前發(fā)過(guò)一篇有關(guān)于自定義preference 在ActivityGroup 的包容下出現(xiàn)UI不能更新的問(wèn)題,當(dāng)時(shí)還以為是Android 的一個(gè)BUG 現(xiàn)在想想真可笑 。其實(shí)是自己對(duì)機(jī)制的理解不夠深刻,看來(lái)以后要多看看源碼才行。
本篇講述內(nèi)容大致為如何自定義preference 開(kāi)始到與ActivityGroup 互用下UI更新的解決方法。
首先從擴(kuò)展preference開(kāi)始:
類文件必須繼承自Preference并實(shí)現(xiàn)構(gòu)造函數(shù),這里我一般實(shí)現(xiàn)兩個(gè)構(gòu)造函數(shù)分別如下(類名為: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}
這里第二個(gè)構(gòu)造函數(shù)第二個(gè)參數(shù)為可以使用attrs 為我們自定義的preference 添加擴(kuò)展的注冊(cè)屬性,比如我們?nèi)绻M麨閿U(kuò)展的preference 添加一個(gè)數(shù)組引用,就可使用如下代碼:
intresouceId=attrs.getAttributeResourceValue(null,"Entries",0);if(resouceId>0)?{
mEntries=getContext().getResources().getTextArray(resouceId);
}
這里的mEntries 是頭部聲明的一個(gè)數(shù)組,我們可以在xml文件通過(guò) Entries=數(shù)組索引得到一個(gè)數(shù)組。在這里不深入為大家示范了。
我們擴(kuò)展preference 有時(shí)想讓其UI更豐富更好看,這里我們可以通過(guò)引用一個(gè)layout 文件為其指定UI,可以通過(guò)實(shí)現(xiàn)如下兩個(gè)回調(diào)函數(shù):
@OverrideprotectedView?onCreateView(ViewGroup?parent)?{//TODO?Auto-generated?method?stubreturnLayoutInflater.from(getContext()).inflate(
R.layout.preference_screen,?parent,false);
}
此回調(diào)函數(shù)與onBindView 一一對(duì)應(yīng),并優(yōu)先執(zhí)行于onBindView ,當(dāng)創(chuàng)建完后將得到的VIEW返回出去給onBindView處理,如下代碼:
@OverrideprotectedvoidonBindView(View?view)?{//TODO?Auto-generated?method?stubsuper.onBindView(view);
canlendar=Calendar.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)));
}
Tip:onBindView 不是必須的,可以將onBindView 里的處理代碼在onCreateView 回調(diào)函數(shù)一并完成然后返回給onBindView ,具體怎么寫看自己的代碼風(fēng)格吧。我個(gè)人比較喜歡這種寫法,比較明了。
下面我們來(lái)了解一下我擴(kuò)展preference 比較常用到的幾個(gè)方法:
Preference another)
與另外一個(gè)preference比較,如果相等則返回0,不相等則返回小于0的數(shù)字。
Object newValue)
如果你希望你擴(kuò)展的Preference 可以支持當(dāng)數(shù)值改變時(shí)候可以調(diào)用OnPreferenceChangeListener此監(jiān)聽(tīng)方法,則必須調(diào)用此方法,查看該方法源碼為:
protectedboolean?callChangeListener(Object?newValue)?{returnmOnChangeListener==null?true:?mOnChangeListener.onPreferenceChange(this,?newValue);
}
源碼簡(jiǎn)單不做過(guò)多介紹,只是實(shí)現(xiàn)一個(gè)接口。
protectedboolean?getPersistedBoolean(boolean?defaultReturnValue)?{if(!shouldPersist())?{returndefaultReturnValue;
}returnmPreferenceManager.getSharedPreferences().getBoolean(mKey,?defaultReturnValue);
}如果你有接觸過(guò)sharePreference 相信一眼就能看出這里它為我們做了什么。
如上,獲取一個(gè)String 數(shù)值
protectedboolean?persistBoolean(boolean?value)?{if(shouldPersist())?{if(value==getPersistedBoolean(!value))?{//It's?already?there,?so?the?same?as?persistingreturntrue;
}
SharedPreferences.Editor?editor=mPreferenceManager.getEditor();
editor.putBoolean(mKey,?value);
tryCommit(editor);returntrue;
}returnfalse;
}
都是sharePreference 的知識(shí),這里不做過(guò)多介紹。其他的跟上面的都 一樣,略過(guò)。
通過(guò)如上的一些設(shè)置,一個(gè)基本的擴(kuò)展preference 就己經(jīng)完成,下面來(lái)講講如果在ActivityGroup 里面讓擴(kuò)展的preference可以更新UI。之前 農(nóng)民伯伯 探討過(guò),他建議我使用onContentChanged()方法,可以使UI更新 ,試了一下發(fā)現(xiàn)有些許問(wèn)題,不過(guò)非常感謝農(nóng)民伯伯。這個(gè)方法是全局刷新,則全部UI都刷新一次,但是這樣不是很合理,我想了一下,那既然此方法可以更新UI那么一定可以行得通,我查看一下源碼,下面把源碼貼出來(lái):
@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?preferenceScreen=getPreferenceScreen();if(preferenceScreen!=null)?{
preferenceScreen.bind(getListView());
}
}
privatestaticfinalintMSG_BIND_PREFERENCES=0;privateHandler?mHandler=newHandler()?{
@OverridepublicvoidhandleMessage(Message?msg)?{switch(msg.what)?{caseMSG_BIND_PREFERENCES:
bindPreferences();break;
}
}
};
原來(lái),這里它是另開(kāi)一條線程來(lái)更新UI,然后當(dāng)值發(fā)生變化時(shí)為其發(fā)送消息,在消息隊(duì)列里面處理UI,只不過(guò)它這里繼承了listActivity 更新了一整個(gè)listView ,那么我們就將它提取出來(lái),只更新我們想要的UI則可。OK,思路出來(lái)了,下面將我擴(kuò)展的一個(gè)preference 的源碼提供出來(lái):
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?implements
OnItemClickListener,?DialogInterface.OnDismissListener?{privateDialog?dialog;privateTextView?title,?summary;privateRelativeLayout?area;privateListView?listView;
Listlist;privateList>listStr;privateCharSequence[]?mEntries;privateString?mValue;privateSimpleAdapter?simple;privatestaticfinalintMSG_BIND_PREFERENCES=0;privateHandler?mHandler=newHandler()?{
@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?stubintresouceId=attrs.getAttributeResourceValue(null,"Entries",0);if(resouceId>0)?{
mEntries=getContext().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?view=LayoutInflater.from(getContext()).inflate(
R.layout.preference_screen,?parent,false);returnview;
}publicvoidbindView(ListView?listview)?{intlength=mEntries.length;inti=0;
listStr=newArrayList>();for(i=0;?i
HashMapmap=newHashMap();
map.put("keyname",?mEntries[i].toString());
listStr.add(map);
}
simple=newSimpleAdapter(getContext(),?listStr,?R.layout.dialog_view,newString[]?{"keyname"},newint[]?{?R.id.text?});
listview.setAdapter(simple);
listview.setOnItemClickListener(this);
}publicvoidshowDialog()?{
listView=newListView(getContext());
bindView(listView);
dialog=newDialog(getContext(),?android.R.style.Theme_NoTitleBar);
dialog.setContentView(listView);
dialog.setOnDismissListener(this);
dialog.show();
}
@OverridepublicvoidonItemClick(AdapterView>parent,?View?view,intposition,longid)?{//TODO?Auto-generated?method?stubmValue=listStr.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.temp=preference;
}publicvoidsetValue(String?value)?{
summary.setText(value);
}publicboolean?callChangeListener(Object?newValue)?{returntemp==null?true:?temp.onPreferenceChange(this,?newValue);
}publicvoidpostBindPreferences()?{if(mHandler.hasMessages(MSG_BIND_PREFERENCES))return;
mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
}
}
然后在preferenceActivity 界面在回調(diào)函數(shù):onPreferenceChange調(diào)用postBindPreferences即可更新。
Tip:這里的onPreferenceChange??調(diào)用postBindPreferences 不是必須的,你同樣可以在內(nèi)部里面實(shí)現(xiàn),通過(guò)執(zhí)行某一操作發(fā)送消息也可。
好了,在這里我要感謝那幾位朋友對(duì)我的幫助,提出了很多寶貴的意見(jiàn)。謝謝。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的android自定义更新,Android 完美解决自定义preference与ActivityGroup UI更新的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 话里话外:企业内控的灵魂——企业文化
- 下一篇: c语言编程思想pdf,C 编程思想(P