Ранее отсоединенный фрагмент остается видимым за текущим после изменения вкладки (с использованием библиотеки поддержки)

Вот мой TabListener:

    public class TabListener<T extends Fragment> implements android.support.v7.app.ActionBar.TabListener {

    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    public TabListener(Activity activity, String tag, Class<T> cl) {
        mActivity = activity;
        mTag = tag;
        mClass = cl;
    }

    @Override
    public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
        // TODO Auto-generated method stub          
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {

        mFragment = ((FragmentActivity) mActivity).getSupportFragmentManager().findFragmentByTag(mTag);   // add this

        if (mFragment == null){ 
            mFragment = android.support.v4.app.Fragment.instantiate(mActivity, mClass.getName()); 
            ft.add(android.R.id.content,mFragment,mTag);
        } else {
            ft.attach(mFragment);
        }             
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        mFragment = ((FragmentActivity) mActivity).getSupportFragmentManager().findFragmentByTag(mTag);   // add this
        if (mFragment != null) {
            //Toast.makeText(mActivity, "detached", Toast.LENGTH_SHORT).show();
            ft.detach(mFragment);
        }
    }

}

И часть моей деятельности:

public class RoadMapActivity extends ActionBarActivity {

ListView generalRoadmapList;
ListView mainRoadmapList;
android.support.v7.app.ActionBar actionBar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_roadmap);

    actionBar = getSupportActionBar();        
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setDisplayUseLogoEnabled(true);       
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    Tab generalTab = actionBar.newTab()
            .setText("General")
            .setTabListener(new TabListener<GeneralListFragment>(this, "general", GeneralListFragment.class));
    actionBar.addTab(generalTab);

    Tab myTab = actionBar.newTab()
                        .setText("My")
                        .setTabListener(new TabListener<MyListFragment>(this, "my", MyListFragment.class));
    actionBar.addTab(myTab);
}

Я попытался изменить viewGroup с android.R.id.content на пользовательскую группу просмотра из макета Activity, произойдет следующее:

У меня есть две вкладки, A и B. После запуска активности активная вкладка - A, а содержимое - фрагмент A. Если переключиться на B, вкладка B становится активной, но содержимое по-прежнему является фрагментом A. Затем вернитесь на вкладку A , и содержимое будет фрагментом B. Перейдите на вкладку B, содержимое будет фрагментом A... без отображения другого фрагмента позади, но с измененным содержимым.

Я пробовал все, что нашел в Google и здесь, но безуспешно. У кого-нибудь есть идея?


person possenH4lt3r    schedule 24.09.2013    source источник


Ответы (2)


Вы создаете свои фрагменты совершенно неправильно. Посмотрите на пересмотренный метод.

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {

   Fragment mFragment;
   switch(tab.getPosition(){ 
     case 0:
       /* create fragment in here based on which tab, mFragment = new ExampleFrag */ 
       break;
     case 1:
       /* create fragment in here based on which tab, mFragment = new ExampleFrag */ 
       break;
   }

   ft.replace(android.R.id.content, mFragment);
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
   // Dont need to do anything.
}

Гораздо проще.

Стоит отметить, что вы не должны использовать android.R.id.content с ActionBarActivity, как до Android 3.0. Панель действий поддержки добавляется в android.R.id.content, и, заменив в ней свой фрагмент, вы удалите ActionBar. (Отвратительно, я знаю.)

person Chris.Jenkins    schedule 24.09.2013

Мое окончательное решение, основанное на ответе Криса:

    public class TabListener<T extends Fragment> implements android.support.v7.app.ActionBar.TabListener {

    private Fragment mFragment;
    private String mTag;
    private boolean added = false;

    private TabListener(String tag, Fragment fragment) {
        mTag = tag;
        mFragment = fragment;
    }

    @Override
    public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
        // TODO Auto-generated method stub          
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {

        if (!added){                
            ft.replace(R.id.list_container,mFragment,mTag);
            added = true;
        } else {
            ft.attach(mFragment);
        } 
    }       

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.detach(mFragment);
    }

}

создание фрагмента (каждая вкладка имеет собственный слушатель):

        Tab myTab = actionBar.newTab()
                        .setText("My")
                        .setTabListener(new TabListener<MyListFragment>("my", new MyListFragment()));
    actionBar.addTab(myTab);

Я завершил ваше решение, потому что таким образом фрагменты не уничтожаются и не создаются на каждой вкладке изменения, вы найдете его в том же состоянии, если вернетесь к ним. Уничтожает и воссоздает только при перезапуске Activity (например, после изменения ориентации).

Большое спасибо Крис!

person possenH4lt3r    schedule 25.09.2013