如何在Android上使用下拉导航模式旋转设备时保留/恢复片段实例?

时间:2014-01-16 22:47:29

标签: android android-fragments android-actionbar

我正在使用ADT在创建使用Dropdown ActionBar的应用程序时创建的默认代码。

问题是我无法保留我的片段视图状态,因为每次在下拉菜单中设置所选项目时都会创建一个新的Fragment实例。

当用户更改选择时,这没关系。问题是设备旋转时。我无法避免重新创建菜单,它必须再次设置所选项目。

我只是不知道如何避免在所选项目未更改时(例如更改方向时)创建新片段实例(并替换旧片段实例)。

这是我的MainActivity代码:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main_activity_layout);

        // Set up the action bar to show a dropdown list.
        final ActionBar actionBar = getActionBar();
        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

        // Set up the dropdown list navigation in the action bar.
        actionBar.setListNavigationCallbacks( new ArrayAdapter<String>(getActionBarThemedContextCompat(),
                android.R.layout.simple_list_item_1,
                android.R.id.text1,
                getResources().getStringArray(R.array.main_menu_array)), this);

    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        // Restore the previously serialized current dropdown position.
        if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
            getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        // Serialize the current dropdown position.
        outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar().getSelectedNavigationIndex());
    }

    @Override
    public boolean onNavigationItemSelected(int position, long id) {
        String[] array = getResources().getStringArray(R.array.main_menu_array);
        String name = array[position];
        if( name.equals(getString(R.string.Pontos)) ) {
            getSupportFragmentManager().beginTransaction().replace(R.id.mainActivityFragContainer, new MainActivityPontosFragment()).commit();
            return true;
        } else if( name.equals(getString(R.string.Sobre)) ) {
            getSupportFragmentManager().beginTransaction().replace(R.id.mainActivityFragContainer, new SobreFragment()).commit();
            return true;
        } else if( name.equals(getString(R.string.Temporizadores))) {
            getSupportFragmentManager().beginTransaction().replace(R.id.mainActivityFragContainer, new TimersListFragment()).commit();
            return true;
        }
        return false;
    }
每次创建菜单时都会调用onNavigationItemSelected,我无法避免它的重现。

但是,当调用onNavigationItemSelected时,如何避免创建新的片段实例?

我想不出更好的方法,但我也无法想象如何实现这一目标。

但我接受其他建议。

由于

修改

我将onNavigationItemSelected更改为this(如果是,则检查最后一个):

        @Override
        public boolean onNavigationItemSelected(int position, long id) {
            String[] array = getResources().getStringArray(R.array.main_menu_array);
            String name = array[position];
            if( name.equals(getString(R.string.Pontos)) ) {
                getSupportFragmentManager().beginTransaction().replace(R.id.mainActivityFragContainer, new MainActivityPontosFragment()).commit();
                return true;
            } else if( name.equals(getString(R.string.Sobre)) ) {
                getSupportFragmentManager().beginTransaction().replace(R.id.mainActivityFragContainer, new SobreFragment()).commit();
                return true;
            } else if( name.equals(getString(R.string.Temporizadores))) {
                MainActivityTimersFragment frag = (MainActivityTimersFragment) getSupportFragmentManager().findFragmentByTag(MainActivityTimersFragment.MY_TAG);
                if( frag == null ) { frag = new MainActivityTimersFragment(); }
                getSupportFragmentManager().beginTransaction().replace(R.id.mainActivityFragContainer, frag, MainActivityTimersFragment.MY_TAG).commit();
                return true;
            }
            return false;
        }

但“frag”总是返回null。

2 个答案:

答案 0 :(得分:1)

我使用以下方法测试了以下内容:

     import android.support.v4.app.Fragment;

使用支持片段,并不是我记得使用常规片段类的所有内容,但这些是我可以根据测试提供的答案。

在屏幕方向更改时,活动将被销毁,并且会调用片段的onDestroyView和onDestroy方法。

但是,当您在Activity的OnCreate方法中调用super.onCreate(savedInstanceState)时,片段将重新创建 - 此时片段将重新附加到您的活动。

您可以使用片段管理器找到这些片段:

Fragment fragment = getSupportFragmentManager().findFragmentByTag(str_ID);

另一种方法是在静态变量中存储对片段的引用。在任何一种情况下,如果在super.OnCreate(savedInstanceState)之前使用,则manger或静态引用将返回NULL。

片段类中的任何非静态变量都将丢失。这是我不确定常规片段类是否表现不同的区域之一。无论如何,您可以覆盖其中一个onDestroy函数,并保存重新创建实例所需的所有变量/数据。

答案 1 :(得分:1)

Altough user3126670对我的问题给出了很好的答案。

我找到了他们的根。

我一直在重建我的活动,因为我的清单只预测了活动的方向变化。我错过了需要添加到API 13 +的screenSize参数。

我所要做的就是:

        <activity
            android:name="br.com.mtcbrasilia.aa.MainActivity"
            android:label="@string/app_name"
            android:configChanges="locale|orientation|screenSize" <---add this
            android:launchMode="singleTop" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
        </activity>