Double fragment rotating Android with ActionBar

后端 未结 4 701
轻奢々
轻奢々 2020-12-24 08:33

I\'ve made a simple Android Activity with an ActionBar to switch between 2 fragments. It\'s all ok until I rotate the device. In facts, when I rotate I\'ve got 2 fragment on

4条回答
  •  天涯浪人
    2020-12-24 08:42

    Thanks Martin and asclepix for theirs solutions. I have 3 tabs and first tab contains 2 fragments, like this:

    
    
        
    
        
    
    
    

    Using onRestoreInstanceState, onSaveInstanceState and savedInstanceState.remove("android:support:fragments"); methods and statement working almost fine except if your active tab is not the first one and rotate and click on first, a clear display appears and only for the second click on the first tab came the right fragment display. After debugging code I recognized that the first addTab always calls an onTabSelected event in the tab listener, with a fragment add method and then when the setSelectedNavigationItem is called from onRestoreInstanceState a detach is executed on the first tab and an add for other one. This unecessary add calling is fixed in my solution.

    My activity

    protected void onCreate(Bundle savedInstanceState) {
        boolean firstTabIsNotAdded = false;
        if (savedInstanceState != null) {
            savedInstanceState.remove("android:support:fragments");
            firstTabIsNotAdded = savedInstanceState.getInt(SELETED_TAB_INDEX) != 0;
        }
        super.onCreate(savedInstanceState);
    
        setContentView(R.layout.activity_main);
    
    // codes before adding tabs
    
        actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    
    
        tabStartAndStop = actionBar.newTab().setText(getString(R.string.tab_title_start_and_stop))
                .setTabListener(
                        new FragmentTabListener(this, 
                                getString(R.string.tab_title_start_and_stop_id), 
                                StartStopFragment.class,
                                firstTabIsNotAdded));
        tabHistory = actionBar.newTab().setText(getString(R.string.tab_title_history))
                .setTabListener(
                        new FragmentTabListener(this, 
                                getString(R.string.tab_title_history_id), 
                                HistoryFragment.class,
                                false));
        tabRiporting = actionBar.newTab().setText(getString(R.string.tab_title_reporting))
                .setTabListener(
                        new FragmentTabListener(this, 
                                getString(R.string.tab_title_reporting_id), 
                                ReportingFragment.class,
                                false));
    
        actionBar.addTab(tabStartAndStop);
    
            actionBar.addTab(tabHistory);
            actionBar.addTab(tabRiporting);
    
        }
    
        @Override
        protected void onRestoreInstanceState(Bundle savedInstanceState) {
            if (savedInstanceState != null) {
                int index = savedInstanceState.getInt(SELETED_TAB_INDEX);
                actionBar.setSelectedNavigationItem(index);
            }
            super.onRestoreInstanceState(savedInstanceState);
        }
    
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            // Save the index of the currently selected tab
            outState.putInt(SELETED_TAB_INDEX, getSupportActionBar().getSelectedTab().getPosition());
        }
    

    And the modified tab listener

    public class FragmentTabListener implements com.actionbarsherlock.app.ActionBar.TabListener {
        private Fragment mFragment;
        private final Activity mFragmentActivity;
        private final String mTag;
        private final Class mClass;
        private boolean doNotAdd;
    
        /** Constructor used each time a new tab is created.
          * @param activity  The host Activity, used to instantiate the fragment
          * @param tag  The identifier tag for the fragment
          * @param clz  The fragment's Class, used to instantiate the fragment
          */
        public FragmentTabListener(Activity activity, String tag, Class clz, boolean doNotAdd) {
            mFragmentActivity = activity;
            mTag = tag;
            mClass = clz;
            this.doNotAdd = doNotAdd;
        }
    
        /* The following are each of the ActionBar.TabListener callbacks */
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
    
            // Check if the fragment is already initialized
            if (mFragment == null) {
                // If not, instantiate and add it to the activity
                if(doNotAdd){
                    doNotAdd = false;
                }else{
                    mFragment = Fragment.instantiate(mFragmentActivity, mClass.getName());
                    ft.add(android.R.id.content, mFragment, mTag);
                }
            } else {
                // If it exists, simply attach it in order to show it
                ft.attach(mFragment);
            }
        }
    
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            if (mFragment != null) {
                // Detach the fragment, because another one is being attached
                ft.detach(mFragment);
            }
        }
    
        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            // User selected the already selected tab. Usually do nothing.
        }
    }
    

提交回复
热议问题