Android PreferenceActivity点击Header是如何处理的?

2023-05-16

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

 

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

 

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

1、单屏幕(SinglePane)

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

public void onHeaderClick(Header header, int position) {
    	Log.d(LOG_TAG, "Settings onHeaderClick Header is:"+header.title+",position is:"+position+",mLastHeader is:"+mLastHeader);
    	
        boolean revert = false;
        if (header.id == R.id.account_add) {
            revert = true;
        }
        Log.d(LOG_TAG, "Settings onHeaderClick Header id is:"+header.id+", R.id.account_add is:"+R.id.account_add+",revert is:"+revert);
        super.onHeaderClick(header, position);

        if (revert && mLastHeader != null) {
            highlightHeader((int) mLastHeader.id);
        } else {
            mLastHeader = header;
        }
    }

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

主要执行父类的onHeaderClick方法。

1.2、

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);
        }
    }

因为mSinglePane为true,故执行startWithFragment。

1.3、

Intent intent = onBuildStartFragmentIntent(fragmentName, args, titleRes, shortTitleRes);
        if (resultTo == null) {
            startActivity(intent);
        } else {
            resultTo.startActivityForResult(intent, resultRequestCode);
        }

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

public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
            int titleRes, int shortTitleRes) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setClass(this, getClass());
        intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
        intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
        intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE, titleRes);
        intent.putExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, shortTitleRes);
        intent.putExtra(EXTRA_NO_HEADERS, true);
        return intent;
    }

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

Settings.java

public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
            int titleRes, int shortTitleRes) {
        Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
                titleRes, shortTitleRes);

        // some fragments want to avoid split actionbar
        if (DataUsageSummary.class.getName().equals(fragmentName) ||
                PowerUsageSummary.class.getName().equals(fragmentName) ||
                AccountSyncSettings.class.getName().equals(fragmentName) ||
                UserDictionarySettings.class.getName().equals(fragmentName)) {
            intent.putExtra(EXTRA_CLEAR_UI_OPTIONS, true);
        }

        intent.setClass(this, SubSettings.class);
        return intent;
    }

这里主要是为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执行。

public class SubSettings extends Settings {
}

1.6、在Settings.java的onCreate中:

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

private void getMetaData() {
        try {
            ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
                    PackageManager.GET_META_DATA);
            if (ai == null || ai.metaData == null) return;
            mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
            mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
            
            // Check if it has a parent specified and create a Header object
            final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
            String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
            if (parentFragmentClass != null) {
                mParentHeader = new Header();
                mParentHeader.fragment = parentFragmentClass;
                if (parentHeaderTitleRes != 0) {
                    mParentHeader.title = getResources().getString(parentHeaderTitleRes);
                }
            }
        } catch (NameNotFoundException nnfe) {
            // No recovery
        }
    }
public Intent getIntent() {
        Intent superIntent = super.getIntent();
        String startingFragment = getStartingFragmentClass(superIntent);
        // This is called from super.onCreate, isMultiPane() is not yet reliable
        // Do not use onIsHidingHeaders either, which relies itself on this method
        if (startingFragment != null && !onIsMultiPane()) {
            Intent modIntent = new Intent(superIntent);
            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
            Bundle args = superIntent.getExtras();
            if (args != null) {
                args = new Bundle(args);
            } else {
                args = new Bundle();
            }
            args.putParcelable("intent", superIntent);
            modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
            return modIntent;
        }
        return superIntent;
    }

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

String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
        Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
        int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
        int initialShortTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, 0);


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

if (initialFragment != null && mSinglePane) {
                // If we are just showing a fragment, we want to run in
                // new fragment mode, but don't need to compute and show
                // the headers.
                switchToHeader(initialFragment, initialArguments);
                if (initialTitle != 0) {
                    CharSequence initialTitleStr = getText(initialTitle);
                    CharSequence initialShortTitleStr = initialShortTitle != 0
                            ? getText(initialShortTitle) : null;
                    showBreadCrumbs(initialTitleStr, initialShortTitleStr);
                }

            } 

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

if (initialFragment != null && mSinglePane) {
            // Single pane, showing just a prefs fragment.
            findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE);
            mPrefsContainer.setVisibility(View.VISIBLE);
            if (initialTitle != 0) {
                CharSequence initialTitleStr = getText(initialTitle);
                CharSequence initialShortTitleStr = initialShortTitle != 0
                        ? getText(initialShortTitle) : null;
                showBreadCrumbs(initialTitleStr, initialShortTitleStr);
            }
        } 


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

 

 

2、双屏幕(平板)

2.1、首先执行单击事件

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);
        }
    }


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

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

2.2、

if (mCurHeader == header) {
            // This is the header we are currently displaying.  Just make sure
            // to pop the stack up to its root state.
            getFragmentManager().popBackStack(BACK_STACK_PREFS,
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
        } else {
            int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader);
            switchToHeaderInner(header.fragment, header.fragmentArguments, direction);
            setSelectedHeader(header);
        }

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

getFragmentManager().popBackStack(BACK_STACK_PREFS,
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);


否则:

int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader);
            switchToHeaderInner(header.fragment, header.fragmentArguments, direction);
            setSelectedHeader(header);

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

我们看switchToHeaderInnr方法。

2.3、

getFragmentManager().popBackStack(BACK_STACK_PREFS,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);
        Fragment f = Fragment.instantiate(this, fragmentName, args);
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        transaction.replace(com.android.internal.R.id.prefs, f);
        transaction.commitAllowingStateLoss();

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

 

2.4,最后执行setSelectedHeader方法。

void setSelectedHeader(Header header) {
        mCurHeader = header;
        int index = mHeaders.indexOf(header);
        if (index >= 0) {
            getListView().setItemChecked(index, true);
        } else {
            getListView().clearChoices();
        }
        showBreadCrumbs(header);
    }

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

2.5、

void showBreadCrumbs(Header header) {
        if (header != null) {
            CharSequence title = header.getBreadCrumbTitle(getResources());
            if (title == null) title = header.getTitle(getResources());
            if (title == null) title = getTitle();
            showBreadCrumbs(title, header.getBreadCrumbShortTitle(getResources()));
        } else {
            showBreadCrumbs(getTitle(), null);
        }
    }

 

 if (mFragmentBreadCrumbs == null) {
            View crumbs = findViewById(android.R.id.title);
            // For screens with a different kind of title, don't create breadcrumbs.
            try {
                mFragmentBreadCrumbs = (FragmentBreadCrumbs)crumbs;
            } catch (ClassCastException e) {
                return;
            }
            if (mFragmentBreadCrumbs == null) {
                if (title != null) {
                    setTitle(title);
                }
                return;
            }
            mFragmentBreadCrumbs.setMaxVisible(2);
            mFragmentBreadCrumbs.setActivity(this);
        }
        mFragmentBreadCrumbs.setTitle(title, shortTitle);
        mFragmentBreadCrumbs.setParentTitle(null, null, null);



 

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

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

Settings.java重新了switchHeader方法:

public void switchToHeader(Header header) {
        if (!mInLocalHeaderSwitch) {
            mCurrentHeader = null;
            mParentHeader = null;
        }
        super.switchToHeader(header);
    }


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

 

 

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

Intent intent=new Intent();
//		intent.setClassName(this, "c");
//		intent.setAction("android.intent.action.PICK_ACTIVITY");
		intent.setAction("android.settings.WIFI_IP_SETTINGS");
		startActivity(intent);

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

 

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

首先Settigns.java的onCreate方法。

1、

protected void onCreate(Bundle savedInstanceState) {
        if (getIntent().getBooleanExtra(EXTRA_CLEAR_UI_OPTIONS, false)) {
            getWindow().setUiOptions(0);
        }

        getMetaData();
        mInLocalHeaderSwitch = true;
        super.onCreate(savedInstanceState);
        mInLocalHeaderSwitch = false;

        if (!onIsHidingHeaders() && onIsMultiPane()) {
            highlightHeader();
            // Force the title so that it doesn't get overridden by a direct launch of
            // a specific settings screen.
            setTitle(R.string.settings_label);
        }

        // Retrieve any saved state
        if (savedInstanceState != null) {
            mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
            mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
        }

        // If the current header was saved, switch to it
        if (savedInstanceState != null && mCurrentHeader != null) {
            //switchToHeaderLocal(mCurrentHeader);
            showBreadCrumbs(mCurrentHeader.title, null);
        }

        if (mParentHeader != null) {
            setParentTitle(mParentHeader.title, null, new OnClickListener() {
                public void onClick(View v) {
                    switchToParent(mParentHeader.fragment);
                }
            });
        }

        // TODO Add support for android.R.id.home in all Setting's onOptionsItemSelected
        // getActionBar().setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP,
        // ActionBar.DISPLAY_HOME_AS_UP);
    }

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

2、

public Intent getIntent() {
        Intent superIntent = super.getIntent();
        String startingFragment = getStartingFragmentClass(superIntent);
        // This is called from super.onCreate, isMultiPane() is not yet reliable
        // Do not use onIsHidingHeaders either, which relies itself on this method
        if (startingFragment != null && !onIsMultiPane()) {
            Intent modIntent = new Intent(superIntent);
            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
            Bundle args = superIntent.getExtras();
            if (args != null) {
                args = new Bundle(args);
            } else {
                args = new Bundle();
            }
            args.putParcelable("intent", superIntent);
            modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
            return modIntent;
        }
        return superIntent;
    }

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

protected String getStartingFragmentClass(Intent intent) {
        if (mFragmentClass != null) return mFragmentClass;

        String intentClass = intent.getComponent().getClassName();
        if (intentClass.equals(getClass().getName())) return null;

        if ("com.android.settings.ManageApplications".equals(intentClass)
                || "com.android.settings.RunningServices".equals(intentClass)
                || "com.android.settings.applications.StorageUse".equals(intentClass)) {
            // Old names of manage apps.
            intentClass = com.android.settings.applications.ManageApplications.class.getName();
        }

        return intentClass;
    }

这个方法中,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方法。

private void getMetaData() {
        try {
            ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
                    PackageManager.GET_META_DATA);
            if (ai == null || ai.metaData == null) return;
            mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
            mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
            
            // Check if it has a parent specified and create a Header object
            final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
            String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
            if (parentFragmentClass != null) {
                mParentHeader = new Header();
                mParentHeader.fragment = parentFragmentClass;
                if (parentHeaderTitleRes != 0) {
                    mParentHeader.title = getResources().getString(parentHeaderTitleRes);
                }
            }
        } catch (NameNotFoundException nnfe) {
            // No recovery
        }
    }

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

<activity android:name="Settings$AdvancedWifiSettingsActivity"
                android:label="@string/wifi_advanced_settings_label"
                android:configChanges="orientation|keyboardHidden|screenSize"
                android:clearTaskOnLaunch="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.settings.WIFI_IP_SETTINGS" />
                <category android:name="android.intent.category.VOICE_LAUNCH" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                android:value="com.android.settings.wifi.AdvancedWifiSettings" />
            <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
                android:resource="@id/wifi_settings" />
            <meta-data android:name="com.android.settings.PARENT_FRAGMENT_TITLE"
                android:resource="@string/wifi_settings" />
            <meta-data android:name="com.android.settings.PARENT_FRAGMENT_CLASS"
                android:value="com.android.settings.Settings$WifiSettingsActivity" />
        </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执行,接下来会执行:

mInLocalHeaderSwitch = true;
        super.onCreate(savedInstanceState);
        mInLocalHeaderSwitch = false;

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

if (!mSinglePane) {
                        if (initialFragment == null) {
                            Header h = onGetInitialHeader();
                            switchToHeader(h);
                        } else {
                            switchToHeader(initialFragment, initialArguments);
                        }
                    }

Settings.java重写了switchToHeader方法。

public void switchToHeader(Header header) {
        if (!mInLocalHeaderSwitch) {
            mCurrentHeader = null;
            mParentHeader = null;
        }
        super.switchToHeader(header);
    }

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

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

 

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

public Header onGetInitialHeader() {
        String fragmentClass = getStartingFragmentClass(super.getIntent());
        if (fragmentClass != null) {
            Header header = new Header();
            header.fragment = fragmentClass;
            header.title = getTitle();
            header.fragmentArguments = getIntent().getExtras();
            mCurrentHeader = header;
            return header;
        }

        return mFirstHeader;
    }

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

if (!onIsHidingHeaders() && onIsMultiPane()) {
            highlightHeader();
            // Force the title so that it doesn't get overridden by a direct launch of
            // a specific settings screen.
            setTitle(R.string.settings_label);
        }
private void highlightHeader() {
        if (mTopLevelHeaderId != 0) {
            Integer index = mHeaderIndexMap.get(mTopLevelHeaderId);
            if (index != null) {
                getListView().setItemChecked(index, true);
                getListView().smoothScrollToPosition(index);
            }
        }
    }


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


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

mFirstHeader的初始化

if (mFirstHeader == null &&
                        HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
                    mFirstHeader = header;
                }

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

mFirstHeader的使用:

  • public Header onGetInitialHeader() {
            String fragmentClass = getStartingFragmentClass(super.getIntent());
            if (fragmentClass != null) {
                Header header = new Header();
                header.fragment = fragmentClass;
                header.title = getTitle();
                header.fragmentArguments = getIntent().getExtras();
                mCurrentHeader = header;
                return header;
            }
    
            return mFirstHeader;
        }

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

  • public void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
    
            // If it is not launched from history, then reset to top-level
            if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0
                    && mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) {
                switchToHeaderLocal(mFirstHeader);
            }
        }

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

初始化:

public Header onGetInitialHeader() {
        String fragmentClass = getStartingFragmentClass(super.getIntent());
        if (fragmentClass != null) {
            Header header = new Header();
            header.fragment = fragmentClass;
            header.title = getTitle();
            header.fragmentArguments = getIntent().getExtras();
            mCurrentHeader = header;
            return header;
        }

        return mFirstHeader;
    }

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

另外的一处初始化:

private void switchToParent(String className) {
        final ComponentName cn = new ComponentName(this, className);
        try {
            final PackageManager pm = getPackageManager();
            final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA);

            if (parentInfo != null && parentInfo.metaData != null) {
                String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
                CharSequence fragmentTitle = parentInfo.loadLabel(pm);
                Header parentHeader = new Header();
                parentHeader.fragment = fragmentClass;
                parentHeader.title = fragmentTitle;
                mCurrentHeader = parentHeader;

                switchToHeaderLocal(parentHeader);
                highlightHeader();

                mParentHeader = new Header();
                mParentHeader.fragment
                        = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
                mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
            }
        } catch (NameNotFoundException nnfe) {
            Log.w(LOG_TAG, "Could not find parent activity : " + className);
        }
    }

使用:

在onCreate中。

if (savedInstanceState != null) {
            mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
            mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
        }

        // If the current header was saved, switch to it
        if (savedInstanceState != null && mCurrentHeader != null) {
            //switchToHeaderLocal(mCurrentHeader);
            showBreadCrumbs(mCurrentHeader.title, null);
        }


三、mParentHeader,

初始化:

private void getMetaData() {
        try {
            ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
                    PackageManager.GET_META_DATA);
            if (ai == null || ai.metaData == null) return;
            mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
            mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
            
            // Check if it has a parent specified and create a Header object
            final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
            String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
            if (parentFragmentClass != null) {
                mParentHeader = new Header();
                mParentHeader.fragment = parentFragmentClass;
                if (parentHeaderTitleRes != 0) {
                    mParentHeader.title = getResources().getString(parentHeaderTitleRes);
                }
            }
        } catch (NameNotFoundException nnfe) {
            // No recovery
        }
    }


使用如上面的mCurrentHeader。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android PreferenceActivity点击Header是如何处理的? 的相关文章

  • 如何在android中点击画布上绘制的圆圈?

    我正在开发一个人脸检测应用程序 在这个应用程序中 我必须在脸上的眼睛和嘴巴用户可以点击拖动圆圈 在检测到的人脸上根据自己设置位置 因此 所有圆圈都已成功绘制在脸上 但我无法单击特定圆圈并使用缩小选项在整个脸上移动 请建议我有关相同问题的正确
  • 在phonegap中播放本地声音

    我有一个 wav文件在我的www文件夹 我正在使用 jQuery 和以下代码 警报响起 但声音不播放 难道我做错了什么
  • 更改首选项的背景颜色

    我有一个PreferenceCategory xml 文件 我已经在其中定义了所有首选项 我从扩展的类中调用它PreferenceActivity 我无法设置设置屏幕的背景 该屏幕是在如下所示的 xml 文件的帮助下显示的 请看我已经定义了
  • Sqlite 查询检查 - 小于和大于

    return mDb query DATABASE TABLE new String KEY ROWID KEY LEVEL KEY LEVEL gt 3 lt 5 null null null null 我究竟做错了什么 它返回的值全部高
  • 为网络和/或持久存储序列化 Android Bundle?

    我需要序列化一个全面的应用程序 游戏 状态 以便通过网络传输或保存到磁盘并在以后检索 当然 捆绑包用于在多个用例中保存 恢复状态 因此使用它们将是理想的选择 但是 由于某种原因 Bundle 不可序列化 寻找解决方案只发现了将 Bundle
  • 不使用 CookieManager 的 Android 会话 cookie

    我的应用程序进行多次网络调用以获得身份验证 我需要将此会话存储在 cookie 中 我想使用 Cookie Manager 但经过一些研究后 我发现它仅适用于 API 9 及更高版本 并且我的应用程序需要向后兼容 我使用 HTTPURLCo
  • 明文 HTTP 流量...不允许

    我的程序从用户那里获取一个 URL 因此它可以向互联网上的任何网站发出请求 我试图让这成为可能 我查找了有关 Android HTTP Cleartext 错误的所有答案 并做了这个 但它仍然不允许我连接我的测试本地 PHP 服务器 我在这
  • 用于代码生成的 ANTLR 工具版本 4.7.1 与当前运行时版本 4.5.3 不匹配

    我正在开发一个 Android 应用程序 当前使用 DSL 和一些库 突然构建给了我这个错误 任务 app kaptDebugKotlin 失败 用于代码生成的 ANTLR 工具版本 4 7 1 与当前运行时版本 4 5 3 不匹配 用于解
  • 安卓;在 AdapterViewFlipper 上设置输入/输出动画:未知的动画师名称翻译

    我有一些非常简单的动画 可以与 ViewFlipper 完美配合 但如果我尝试在 AdapterViewFlipper 输入 输出上设置它们 我会收到运行时错误 未知的动画师名称翻译 查看每个方法的相应方法 看起来 ViewFlipper
  • 如何知道点击的widget id?

    我已经实施了一个widget与ImageButton and a TextView That ImageButton启动一个activity当它被点击时 这activity使用用户在活动上写入的内容更新小部件文本EditText 现在的问题
  • 我可以使用“导入 com.facebook.FacebookSdk;”使用 Facebook SDK 3.23.1?

    在我的 app build gradle 文件中 我有compile com facebook android facebook android sdk 3 23 1 在我的 BaseActivity java 文件 其中有 public
  • MAT(Eclipse 内存分析器)- 如何从内存转储中查看位图

    I m analyzing memory usage of my Android app with help of Eclipse Memory Analyzer http www eclipse org mat also known as
  • 对基本适配器类及其功能的疑问

    我正在尝试自定义列表视图 我使用数组列表添加对象列表 并将其发送到扩展基本适配器的类 当我扩展基本适配器类时 它实现了一些方法 例如 getView 等 在 getView 中 我将其发送到将名称 数据 分配给 XML 格式的自定义菜单的类
  • MPAndroidChart:组合图表

    我在用MPAndroidChart 库 https github com PhilJay MPAndroidChart 我想用CombinedChart创建这样的图表 那可能吗 我尝试了一下 但似乎不起作用 因为 这些条目没有按我的预期工作
  • 我可以在主线程上读取一个小 txt 文件,还是应该始终避免那里的 I/O?

    我正在读取一个小的 json 文件 其中有几行 它存储在用户设备的内部应用程序文件夹中 我所做的就是这样 JSONObject jsonObject new JSONObject MyUtils inputStreamToString My
  • 在 Android SDK 中通过单击按钮更改背景颜色不起作用

    我有一个简单的程序 可以在单击按钮后更改背景颜色 但它不起作用 public class ChangeBackgroundActivity extends Activity Called when the activity is first
  • Android 视图和视图组

    在安卓中ViewGroup继承自View A ViewGroup是一个容器 里面装有Views ViewGroup LinearLayout View TextView 为什么 Android 的人们将这种关系定义为Inheritance而
  • 在 TextView onTextChanged 上设置文本

    我有一个定义为类属性的文本视图 以便我可以在整个类中访问它 在 onCreate 方法中我执行以下操作 chars TextView findViewById R id chars chars setText 300 之后 public v
  • 在android中的日期选择器对话框中显示当前日期

    我多次尝试在日期选择器对话框中显示当前日期 但失败了 它显示 1 1 1990 我已经遵循了堆栈溢出的一些答案 但不幸的是这些对我不起作用 谁能解释一下在日期选择器对话框中显示当前日期的代码 谢谢 It may help you publi
  • 将数据放入短信发送意图中?

    我想发送短信 如果文字太长 我会将其分成多条消息 我试图将一些额外的信息放入 已发送 意图中 以了解哪个部分已发送 以及所有部分何时完成 ArrayList

随机推荐