转载请注明出处:http://blog.csdn.net/droyon/article/details/18009373

本文讲述PreferenceActivity中单击事件的处理,重点记述mCurrentHeader以及设置源代码Settings中的mLastHeader、mCurrentHeader、mParentHeader的作用。主要以多屏幕为例。

在PreferenceActivity中,当我们点击Header时,其处理流程分为 单屏幕和双屏幕两套流程。

1、单屏幕(SinglePane)

1.1、点击每一项,执行如下代码.

[java] view plain copy
  1. publicvoidonHeaderClick(Headerheader,intposition){
  2. Log.d(LOG_TAG,"SettingsonHeaderClickHeaderis:"+header.title+",positionis:"+position+",mLastHeaderis:"+mLastHeader);
  3. booleanrevert=false;
  4. if(header.id==R.id.account_add){
  5. revert=true;
  6. }
  7. Log.d(LOG_TAG,"SettingsonHeaderClickHeaderidis:"+header.id+",R.id.account_addis:"+R.id.account_add+",revertis:"+revert);
  8. super.onHeaderClick(header,position);
  9. if(revert&&mLastHeader!=null){
  10. highlightHeader((int)mLastHeader.id);
  11. }else{
  12. mLastHeader=header;
  13. }
  14. }

关于hightlightHeader下面有详细介绍,这里就不介绍了。

主要执行父类的onHeaderClick方法。

1.2、

[java] view plain copy
  1. publicvoidonHeaderClick(Headerheader,intposition){
  2. if(header.fragment!=null){
  3. if(mSinglePane){
  4. inttitleRes=header.breadCrumbTitleRes;
  5. intshortTitleRes=header.breadCrumbShortTitleRes;
  6. if(titleRes==0){
  7. titleRes=header.titleRes;
  8. shortTitleRes=0;
  9. }
  10. startWithFragment(header.fragment,header.fragmentArguments,null,0,
  11. titleRes,shortTitleRes);
  12. }else{
  13. switchToHeader(header);
  14. }
  15. }elseif(header.intent!=null){
  16. startActivity(header.intent);
  17. }
  18. }

因为mSinglePane为true,故执行startWithFragment。

1.3、

[java] view plain copy
  1. Intentintent=onBuildStartFragmentIntent(fragmentName,args,titleRes,shortTitleRes);
  2. if(resultTo==null){
  3. startActivity(intent);
  4. }else{
  5. resultTo.startActivityForResult(intent,resultRequestCode);
  6. }

我们看到这里会执行onBuildStartFragmentIntent。
1.4、

[java] view plain copy
  1. publicIntentonBuildStartFragmentIntent(StringfragmentName,Bundleargs,
  2. inttitleRes,intshortTitleRes){
  3. Intentintent=newIntent(Intent.ACTION_MAIN);
  4. intent.setClass(this,getClass());
  5. intent.putExtra(EXTRA_SHOW_FRAGMENT,fragmentName);
  6. intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS,args);
  7. intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE,titleRes);
  8. intent.putExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE,shortTitleRes);
  9. intent.putExtra(EXTRA_NO_HEADERS,true);
  10. returnintent;
  11. }

这个方法在子类中有重写。

Settings.java

[java] view plain copy
  1. publicIntentonBuildStartFragmentIntent(StringfragmentName,Bundleargs,
  2. inttitleRes,intshortTitleRes){
  3. Intentintent=super.onBuildStartFragmentIntent(fragmentName,args,
  4. titleRes,shortTitleRes);
  5. //somefragmentswanttoavoidsplitactionbar
  6. if(DataUsageSummary.class.getName().equals(fragmentName)||
  7. PowerUsageSummary.class.getName().equals(fragmentName)||
  8. AccountSyncSettings.class.getName().equals(fragmentName)||
  9. UserDictionarySettings.class.getName().equals(fragmentName)){
  10. intent.putExtra(EXTRA_CLEAR_UI_OPTIONS,true);
  11. }
  12. intent.setClass(this,SubSettings.class);
  13. returnintent;
  14. }

这里主要是为intent增加了SubSettings.class,因为Header中的fragment,需要有个Activity依附。

ps://******log信息

01-08 21:55:05.857: D/Hlwang_Settings(25569): Settings onBuildStartFragmentIntent fragmentName is:com.android.settings.wifi.WifiSettings

//*************************

1.5、由1.3可知,这个intent会被startActivity(intent)发送出去。

Intent会被SubSettings接收,由于SubSettings继承自Settigns.java,因此,这个Intent还会被Settings.java执行。

[java] view plain copy
  1. publicclassSubSettingsextendsSettings{
  2. }

1.6、在Settings.java的onCreate中:

在onCreate中会执行getMeteData以及getIntent。这两个方法共同作用得到了mFragmentClass。然后执行super.onCreate

[java] view plain copy
  1. privatevoidgetMetaData(){
  2. try{
  3. ActivityInfoai=getPackageManager().getActivityInfo(getComponentName(),
  4. PackageManager.GET_META_DATA);
  5. if(ai==null||ai.metaData==null)return;
  6. mTopLevelHeaderId=ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
  7. mFragmentClass=ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
  8. //CheckifithasaparentspecifiedandcreateaHeaderobject
  9. finalintparentHeaderTitleRes=ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
  10. StringparentFragmentClass=ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
  11. if(parentFragmentClass!=null){
  12. mParentHeader=newHeader();
  13. mParentHeader.fragment=parentFragmentClass;
  14. if(parentHeaderTitleRes!=0){
  15. mParentHeader.title=getResources().getString(parentHeaderTitleRes);
  16. }
  17. }
  18. }catch(NameNotFoundExceptionnnfe){
  19. //Norecovery
  20. }
  21. }
[java] view plain copy
  1. publicIntentgetIntent(){
  2. IntentsuperIntent=super.getIntent();
  3. StringstartingFragment=getStartingFragmentClass(superIntent);
  4. //Thisiscalledfromsuper.onCreate,isMultiPane()isnotyetreliable
  5. //DonotuseonIsHidingHeaderseither,whichreliesitselfonthismethod
  6. if(startingFragment!=null&&!onIsMultiPane()){
  7. IntentmodIntent=newIntent(superIntent);
  8. modIntent.putExtra(EXTRA_SHOW_FRAGMENT,startingFragment);
  9. Bundleargs=superIntent.getExtras();
  10. if(args!=null){
  11. args=newBundle(args);
  12. }else{
  13. args=newBundle();
  14. }
  15. args.putParcelable("intent",superIntent);
  16. modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS,superIntent.getExtras());
  17. returnmodIntent;
  18. }
  19. returnsuperIntent;
  20. }

ps://****log信息

01-08 21:55:05.897: D/Hlwang_Settings(25569): Settings getStartingFragmentClass intentClass is:com.android.settings.SubSettingsgetClassName is:com.android.settings.SubSettings

//***********

PreferenceActivity.java

[java] view plain copy
  1. StringinitialFragment=getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
  2. BundleinitialArguments=getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
  3. intinitialTitle=getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE,0);
  4. intinitialShortTitle=getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE,0);


这样initialFragment得到了初始化,并且。

[java] view plain copy
  1. if(initialFragment!=null&&mSinglePane){
  2. //Ifwearejustshowingafragment,wewanttorunin
  3. //newfragmentmode,butdon'tneedtocomputeandshow
  4. //theheaders.
  5. switchToHeader(initialFragment,initialArguments);
  6. if(initialTitle!=0){
  7. CharSequenceinitialTitleStr=getText(initialTitle);
  8. CharSequenceinitialShortTitleStr=initialShortTitle!=0
  9. ?getText(initialShortTitle):null;
  10. showBreadCrumbs(initialTitleStr,initialShortTitleStr);
  11. }
  12. }

这里跳用switchToHeader将Fragment切换到右边窗体中。

[java] view plain copy
  1. if(initialFragment!=null&&mSinglePane){
  2. //Singlepane,showingjustaprefsfragment.
  3. findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE);
  4. mPrefsContainer.setVisibility(View.VISIBLE);
  5. if(initialTitle!=0){
  6. CharSequenceinitialTitleStr=getText(initialTitle);
  7. CharSequenceinitialShortTitleStr=initialShortTitle!=0
  8. ?getText(initialShortTitle):null;
  9. showBreadCrumbs(initialTitleStr,initialShortTitleStr);
  10. }
  11. }


这里,将左边窗体的Header 列表隐藏。

2、双屏幕(平板)

2.1、首先执行单击事件

[java] view plain copy
  1. publicvoidonHeaderClick(Headerheader,intposition){
  2. if(header.fragment!=null){
  3. if(mSinglePane){
  4. inttitleRes=header.breadCrumbTitleRes;
  5. intshortTitleRes=header.breadCrumbShortTitleRes;
  6. if(titleRes==0){
  7. titleRes=header.titleRes;
  8. shortTitleRes=0;
  9. }
  10. startWithFragment(header.fragment,header.fragmentArguments,null,0,
  11. titleRes,shortTitleRes);
  12. }else{
  13. switchToHeader(header);
  14. }
  15. }elseif(header.intent!=null){
  16. startActivity(header.intent);
  17. }
  18. }


我们在这个方法内看到,首先判断fragment以及intent,然后会根据mSinglePane来判断进入那个逻辑里。mSinglePane是单屏幕或者双屏幕,此处为false。

在双屏幕中,此处会执行switchToHeader(header)方法。

2.2、

[java] view plain copy
  1. if(mCurHeader==header){
  2. //Thisistheheaderwearecurrentlydisplaying.Justmakesure
  3. //topopthestackuptoitsrootstate.
  4. getFragmentManager().popBackStack(BACK_STACK_PREFS,
  5. FragmentManager.POP_BACK_STACK_INCLUSIVE);
  6. }else{
  7. intdirection=mHeaders.indexOf(header)-mHeaders.indexOf(mCurHeader);
  8. switchToHeaderInner(header.fragment,header.fragmentArguments,direction);
  9. setSelectedHeader(header);
  10. }

这里首先会判断mCurrentHeader是否为要切换的header。如果mCurrentHeader == header,那么执行:

[java] view plain copy
  1. getFragmentManager().popBackStack(BACK_STACK_PREFS,
  2. FragmentManager.POP_BACK_STACK_INCLUSIVE);


否则:

[java] view plain copy
  1. intdirection=mHeaders.indexOf(header)-mHeaders.indexOf(mCurHeader);
  2. switchToHeaderInner(header.fragment,header.fragmentArguments,direction);
  3. setSelectedHeader(header);

在这里,direction没有发挥作用。这里应该是判断ListView是向上滚动还是向下滚动。

我们看switchToHeaderInnr方法。

2.3、

[java] view plain copy
  1. getFragmentManager().popBackStack(BACK_STACK_PREFS,
  2. FragmentManager.POP_BACK_STACK_INCLUSIVE);
  3. Fragmentf=Fragment.instantiate(this,fragmentName,args);
  4. FragmentTransactiontransaction=getFragmentManager().beginTransaction();
  5. transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
  6. transaction.replace(com.android.internal.R.id.prefs,f);
  7. transaction.commitAllowingStateLoss();

这个方法处理fragment的切换。例如:我们在左边,点击了Bluetooth的设置项,那么其fragment会在右边显示。

2.4,最后执行setSelectedHeader方法。

[java] view plain copy
  1. voidsetSelectedHeader(Headerheader){
  2. mCurHeader=header;
  3. intindex=mHeaders.indexOf(header);
  4. if(index>=0){
  5. getListView().setItemChecked(index,true);
  6. }else{
  7. getListView().clearChoices();
  8. }
  9. showBreadCrumbs(header);
  10. }

在这个方法中主要处理ListView的setItemChecked状态。如上图中蓝牙设置项的选中底色。并且设置Breadcrumb(标题)

2.5、

[java] view plain copy
  1. voidshowBreadCrumbs(Headerheader){
  2. if(header!=null){
  3. CharSequencetitle=header.getBreadCrumbTitle(getResources());
  4. if(title==null)title=header.getTitle(getResources());
  5. if(title==null)title=getTitle();
  6. showBreadCrumbs(title,header.getBreadCrumbShortTitle(getResources()));
  7. }else{
  8. showBreadCrumbs(getTitle(),null);
  9. }
  10. }

[java] view plain copy
  1. if(mFragmentBreadCrumbs==null){
  2. Viewcrumbs=findViewById(android.R.id.title);
  3. //Forscreenswithadifferentkindoftitle,don'tcreatebreadcrumbs.
  4. try{
  5. mFragmentBreadCrumbs=(FragmentBreadCrumbs)crumbs;
  6. }catch(ClassCastExceptione){
  7. return;
  8. }
  9. if(mFragmentBreadCrumbs==null){
  10. if(title!=null){
  11. setTitle(title);
  12. }
  13. return;
  14. }
  15. mFragmentBreadCrumbs.setMaxVisible(2);
  16. mFragmentBreadCrumbs.setActivity(this);
  17. }
  18. mFragmentBreadCrumbs.setTitle(title,shortTitle);
  19. mFragmentBreadCrumbs.setParentTitle(null,null,null);



//*****************************************************************************************

2.6、在设置应用的源代码中,Settings.java类中。上述的处理存在如下差别。

Settings.java重新了switchHeader方法:

[java] view plain copy
  1. publicvoidswitchToHeader(Headerheader){
  2. if(!mInLocalHeaderSwitch){
  3. mCurrentHeader=null;
  4. mParentHeader=null;
  5. }
  6. super.switchToHeader(header);
  7. }


mInLocalHeaderSwitch在我们点击条目的时候为false,故,Settings.java中定义的mCurrentHeader以及mParentHeader会赋值null。然后执行super.switchToHeader()。

二、外部通过Action进入设置应用的流程。(多屏幕的状态下)

[java] view plain copy
  1. Intentintent=newIntent();
  2. //intent.setClassName(this,"c");
  3. //intent.setAction("android.intent.action.PICK_ACTIVITY");
  4. intent.setAction("android.settings.WIFI_IP_SETTINGS");
  5. startActivity(intent);

通过上述代码,会进入如下界面。

启动这个界面会经历如下流程,

首先Settigns.java的onCreate方法。

1、

[java] view plain copy
  1. protectedvoidonCreate(BundlesavedInstanceState){
  2. if(getIntent().getBooleanExtra(EXTRA_CLEAR_UI_OPTIONS,false)){
  3. getWindow().setUiOptions(0);
  4. }
  5. getMetaData();
  6. mInLocalHeaderSwitch=true;
  7. super.onCreate(savedInstanceState);
  8. mInLocalHeaderSwitch=false;
  9. if(!onIsHidingHeaders()&&onIsMultiPane()){
  10. highlightHeader();
  11. //Forcethetitlesothatitdoesn'tgetoverriddenbyadirectlaunchof
  12. //aspecificsettingsscreen.
  13. setTitle(R.string.settings_label);
  14. }
  15. //Retrieveanysavedstate
  16. if(savedInstanceState!=null){
  17. mCurrentHeader=savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
  18. mParentHeader=savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
  19. }
  20. //Ifthecurrentheaderwassaved,switchtoit
  21. if(savedInstanceState!=null&&mCurrentHeader!=null){
  22. //switchToHeaderLocal(mCurrentHeader);
  23. showBreadCrumbs(mCurrentHeader.title,null);
  24. }
  25. if(mParentHeader!=null){
  26. setParentTitle(mParentHeader.title,null,newOnClickListener(){
  27. publicvoidonClick(Viewv){
  28. switchToParent(mParentHeader.fragment);
  29. }
  30. });
  31. }
  32. //TODOAddsupportforandroid.R.id.homeinallSetting'sonOptionsItemSelected
  33. //getActionBar().setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP,
  34. //ActionBar.DISPLAY_HOME_AS_UP);
  35. }

在这个方法内,首先执行getIntent方法,Settings重新了这个方法。

2、

[java] view plain copy
  1. publicIntentgetIntent(){
  2. IntentsuperIntent=super.getIntent();
  3. StringstartingFragment=getStartingFragmentClass(superIntent);
  4. //Thisiscalledfromsuper.onCreate,isMultiPane()isnotyetreliable
  5. //DonotuseonIsHidingHeaderseither,whichreliesitselfonthismethod
  6. if(startingFragment!=null&&!onIsMultiPane()){
  7. IntentmodIntent=newIntent(superIntent);
  8. modIntent.putExtra(EXTRA_SHOW_FRAGMENT,startingFragment);
  9. Bundleargs=superIntent.getExtras();
  10. if(args!=null){
  11. args=newBundle(args);
  12. }else{
  13. args=newBundle();
  14. }
  15. args.putParcelable("intent",superIntent);
  16. modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS,superIntent.getExtras());
  17. returnmodIntent;
  18. }
  19. returnsuperIntent;
  20. }

在这个方法内,会调用getStartingFragmentClass方法。

[java] view plain copy
  1. protectedStringgetStartingFragmentClass(Intentintent){
  2. if(mFragmentClass!=null)returnmFragmentClass;
  3. StringintentClass=intent.getComponent().getClassName();
  4. if(intentClass.equals(getClass().getName()))returnnull;
  5. if("com.android.settings.ManageApplications".equals(intentClass)
  6. ||"com.android.settings.RunningServices".equals(intentClass)
  7. ||"com.android.settings.applications.StorageUse".equals(intentClass)){
  8. //Oldnamesofmanageapps.
  9. intentClass=com.android.settings.applications.ManageApplications.class.getName();
  10. }
  11. returnintentClass;
  12. }

这个方法中,intentClass为:com.android.settings.Settings$AdvancedWifiSettingsActivity

ps://****************************************************************log信息

01-08 21:10:06.737: D/Hlwang_Settings(15602): Settings getStartingFragmentClass mFragmentClass is:null
01-08 21:10:06.737: D/Hlwang_Settings(15602): Settings getStartingFragmentClass intentClass is:com.android.settings.Settings$AdvancedWifiSettingsActivity

//************************************************

3、我们继续看onCreate方法。在往下会执行getMeteData方法。

[java] view plain copy
  1. privatevoidgetMetaData(){
  2. try{
  3. ActivityInfoai=getPackageManager().getActivityInfo(getComponentName(),
  4. PackageManager.GET_META_DATA);
  5. if(ai==null||ai.metaData==null)return;
  6. mTopLevelHeaderId=ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
  7. mFragmentClass=ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
  8. //CheckifithasaparentspecifiedandcreateaHeaderobject
  9. finalintparentHeaderTitleRes=ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
  10. StringparentFragmentClass=ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
  11. if(parentFragmentClass!=null){
  12. mParentHeader=newHeader();
  13. mParentHeader.fragment=parentFragmentClass;
  14. if(parentHeaderTitleRes!=0){
  15. mParentHeader.title=getResources().getString(parentHeaderTitleRes);
  16. }
  17. }
  18. }catch(NameNotFoundExceptionnnfe){
  19. //Norecovery
  20. }
  21. }

这里,AdvancedWifiSettingsActivity在AndroidManifest.xml中的配置:

[html] view plain copy
  1. <activityandroid:name="Settings$AdvancedWifiSettingsActivity"
  2. android:label="@string/wifi_advanced_settings_label"
  3. android:configChanges="orientation|keyboardHidden|screenSize"
  4. android:clearTaskOnLaunch="true">
  5. <intent-filter>
  6. <actionandroid:name="android.intent.action.MAIN"/>
  7. <actionandroid:name="android.settings.WIFI_IP_SETTINGS"/>
  8. <categoryandroid:name="android.intent.category.VOICE_LAUNCH"/>
  9. <categoryandroid:name="android.intent.category.DEFAULT"/>
  10. </intent-filter>
  11. <meta-dataandroid:name="com.android.settings.FRAGMENT_CLASS"
  12. android:value="com.android.settings.wifi.AdvancedWifiSettings"/>
  13. <meta-dataandroid:name="com.android.settings.TOP_LEVEL_HEADER_ID"
  14. android:resource="@id/wifi_settings"/>
  15. <meta-dataandroid:name="com.android.settings.PARENT_FRAGMENT_TITLE"
  16. android:resource="@string/wifi_settings"/>
  17. <meta-dataandroid:name="com.android.settings.PARENT_FRAGMENT_CLASS"
  18. android:value="com.android.settings.Settings$WifiSettingsActivity"/>
  19. </activity>


故而:mTopLevelId = @+id/wifi_settigns,mFragmentClass为:com.android.settings.wifi.AdvancedWifiSettings,mParentClass为:com.android.settings.Settings$WifiSettingsActivity

ps://************************log信息

01-08 21:10:06.747: D/Hlwang_Settings(15602): Settings getMetaData
01-08 21:10:06.747: D/Hlwang_Settings(15602): Settings getMetaData mFragmentClass is:com.android.settings.wifi.AdvancedWifiSettings
01-08 21:10:06.747: D/Hlwang_Settings(15602): Settings getMetaData parentFragmentClass is:com.android.settings.Settings$WifiSettingsActivity

//******************************
4、继续onCreate执行,接下来会执行:

[java] view plain copy
  1. mInLocalHeaderSwitch=true;
  2. super.onCreate(savedInstanceState);
  3. mInLocalHeaderSwitch=false;

这里会执行super.onCreate方法。之所以用mInLocalHeaderSwitch包裹,主要是因为super.onCreate方法,会执行到PreferenceActitivity.java中的 :

[java] view plain copy
  1. if(!mSinglePane){
  2. if(initialFragment==null){
  3. Headerh=onGetInitialHeader();
  4. switchToHeader(h);
  5. }else{
  6. switchToHeader(initialFragment,initialArguments);
  7. }
  8. }

Settings.java重写了switchToHeader方法。

[java] view plain copy
  1. publicvoidswitchToHeader(Headerheader){
  2. if(!mInLocalHeaderSwitch){
  3. mCurrentHeader=null;
  4. mParentHeader=null;
  5. }
  6. super.switchToHeader(header);
  7. }

这样mInLocalHeaderSwitch为true,不会清楚mCurrentHeader以及mParentHeader。

最后会执行super.switchToHeader方法,这个方法的执行,会将AdvancedWifiSettings加载到如上图所示的右边的区域内。

Settings.java还重新了onGetInitialHeader方法,这个方法为Header赋了正确的值。

[java] view plain copy
  1. publicHeaderonGetInitialHeader(){
  2. StringfragmentClass=getStartingFragmentClass(super.getIntent());
  3. if(fragmentClass!=null){
  4. Headerheader=newHeader();
  5. header.fragment=fragmentClass;
  6. header.title=getTitle();
  7. header.fragmentArguments=getIntent().getExtras();
  8. mCurrentHeader=header;
  9. returnheader;
  10. }
  11. returnmFirstHeader;
  12. }

5、最后一步,给上图左边的部分加上setItemChecked效果。也即是上图中的选中状态底纹。

[java] view plain copy
  1. if(!onIsHidingHeaders()&&onIsMultiPane()){
  2. highlightHeader();
  3. //Forcethetitlesothatitdoesn'tgetoverriddenbyadirectlaunchof
  4. //aspecificsettingsscreen.
  5. setTitle(R.string.settings_label);
  6. }
[java] view plain copy
  1. privatevoidhighlightHeader(){
  2. if(mTopLevelHeaderId!=0){
  3. Integerindex=mHeaderIndexMap.get(mTopLevelHeaderId);
  4. if(index!=null){
  5. getListView().setItemChecked(index,true);
  6. getListView().smoothScrollToPosition(index);
  7. }
  8. }
  9. }


mTopLevelHeaderId,我们在getMeteData方法中得到。


一、在多屏幕中,mFirstHeader的作用主要是为了正确的切换第一个Header。

mFirstHeader的初始化

[java] view plain copy
  1. if(mFirstHeader==null&&
  2. HeaderAdapter.getHeaderType(header)!=HeaderAdapter.HEADER_TYPE_CATEGORY){
  3. mFirstHeader=header;
  4. }

如果为空,那么mFirstHeader为最靠前的第一个category。

mFirstHeader的使用:

  • [java] view plain copy
    1. publicHeaderonGetInitialHeader(){
    2. StringfragmentClass=getStartingFragmentClass(super.getIntent());
    3. if(fragmentClass!=null){
    4. Headerheader=newHeader();
    5. header.fragment=fragmentClass;
    6. header.title=getTitle();
    7. header.fragmentArguments=getIntent().getExtras();
    8. mCurrentHeader=header;
    9. returnheader;
    10. }
    11. returnmFirstHeader;
    12. }

如果getStarttingFragmentClass为null,那么返回mFirstHeader。

  • [java] view plain copy
    1. publicvoidonNewIntent(Intentintent){
    2. super.onNewIntent(intent);
    3. //Ifitisnotlaunchedfromhistory,thenresettotop-level
    4. if((intent.getFlags()&Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)==0
    5. &&mFirstHeader!=null&&!onIsHidingHeaders()&&onIsMultiPane()){
    6. switchToHeaderLocal(mFirstHeader);
    7. }
    8. }

二、mCurrentHeader的作用,显示当前Header的title。

初始化:

[java] view plain copy
  1. publicHeaderonGetInitialHeader(){
  2. StringfragmentClass=getStartingFragmentClass(super.getIntent());
  3. if(fragmentClass!=null){
  4. Headerheader=newHeader();
  5. header.fragment=fragmentClass;
  6. header.title=getTitle();
  7. header.fragmentArguments=getIntent().getExtras();
  8. mCurrentHeader=header;
  9. returnheader;
  10. }
  11. returnmFirstHeader;
  12. }

外部跳转得到了fragmentClass,那么会初始化mCurrentHeader。

另外的一处初始化:

[java] view plain copy
  1. privatevoidswitchToParent(StringclassName){
  2. finalComponentNamecn=newComponentName(this,className);
  3. try{
  4. finalPackageManagerpm=getPackageManager();
  5. finalActivityInfoparentInfo=pm.getActivityInfo(cn,PackageManager.GET_META_DATA);
  6. if(parentInfo!=null&&parentInfo.metaData!=null){
  7. StringfragmentClass=parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
  8. CharSequencefragmentTitle=parentInfo.loadLabel(pm);
  9. HeaderparentHeader=newHeader();
  10. parentHeader.fragment=fragmentClass;
  11. parentHeader.title=fragmentTitle;
  12. mCurrentHeader=parentHeader;
  13. switchToHeaderLocal(parentHeader);
  14. highlightHeader();
  15. mParentHeader=newHeader();
  16. mParentHeader.fragment
  17. =parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
  18. mParentHeader.title=parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
  19. }
  20. }catch(NameNotFoundExceptionnnfe){
  21. Log.w(LOG_TAG,"Couldnotfindparentactivity:"+className);
  22. }
  23. }

使用:

在onCreate中。

[java] view plain copy
  1. if(savedInstanceState!=null){
  2. mCurrentHeader=savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
  3. mParentHeader=savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
  4. }
  5. //Ifthecurrentheaderwassaved,switchtoit
  6. if(savedInstanceState!=null&&mCurrentHeader!=null){
  7. //switchToHeaderLocal(mCurrentHeader);
  8. showBreadCrumbs(mCurrentHeader.title,null);
  9. }


三、mParentHeader,

初始化:

[java] view plain copy
  1. privatevoidgetMetaData(){
  2. try{
  3. ActivityInfoai=getPackageManager().getActivityInfo(getComponentName(),
  4. PackageManager.GET_META_DATA);
  5. if(ai==null||ai.metaData==null)return;
  6. mTopLevelHeaderId=ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
  7. mFragmentClass=ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
  8. //CheckifithasaparentspecifiedandcreateaHeaderobject
  9. finalintparentHeaderTitleRes=ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
  10. StringparentFragmentClass=ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
  11. if(parentFragmentClass!=null){
  12. mParentHeader=newHeader();
  13. mParentHeader.fragment=parentFragmentClass;
  14. if(parentHeaderTitleRes!=0){
  15. mParentHeader.title=getResources().getString(parentHeaderTitleRes);
  16. }
  17. }
  18. }catch(NameNotFoundExceptionnnfe){
  19. //Norecovery
  20. }
  21. }


使用如上面的mCurrentHeader。

更多相关文章

  1. 【翻译】4种经典的Android屏幕自适应解决方案
  2. Android网络通信(4):WebKit
  3. Qt Android(安卓)部署项目时报错
  4. android MediaPlayer 几种播放方式
  5. ContentProvider何时创建?SQLiteDatabase方法何时执行?
  6. Path
  7. Android接收短信-createFromPdu
  8. Android属性动画---Property Animation(六)
  9. 倍数提高工作效率的 Android(安卓)Studio 奇技

随机推荐

  1. Android 开发技术周报 Issue#299
  2. 【Android】View组件
  3. android中setVisibility的用法
  4. Android UI性能问题探讨
  5. 下载 android 源码错误curl: (6) couldn'
  6. 聚焦 Android 11:游戏开发新工具
  7. Android-透明状态栏
  8. android jni (jni_onload方式)
  9. Android中使用SQLite数据库详解
  10. Android之Activity概述