Подтвердить что ты не робот

Фрагменты не работают правильно после изменения ориентации

У меня проблема с Fragments и изменением ориентации.

У меня есть приложение, которое имеет MainActivity, который управляет переключением Fragments через панель действий с вкладками. Вот код для панели вкладок и при выборе вкладки.

private class MyTabListener <T extends android.support.v4.app.Fragment> implements ActionBar.TabListener {
    private android.support.v4.app.Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    public MyTabListener(SherlockFragmentActivity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    @Override
    public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft) {
        if (mFragment == null){ // check to see if the fragment has already been initialised. If not create a new one.
            mFragment = android.support.v4.app.Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content,mFragment,mTag);
        } else {
            ft.attach(mFragment); // if the fragment has been initialised attach it to the current activity
        }
    }

    @Override
    public void onTabUnselected(Tab tab, android.support.v4.app.FragmentTransaction ft) {
        if (mFragment != null){
            ft.detach(mFragment); // when a fragment is no longer needed, detach it from the activity but dont destroy it
        }
    }

    @Override
    public void onTabReselected(Tab tab, android.support.v4.app.FragmentTransaction ft) {

    }

Как я вижу, все работает нормально, когда приложение загружается в портретном режиме. Когда я вращаюсь, по какой-то причине добавляется другой экземпляр Fragment1, а затем не отделяется, когда выбрана другая вкладка. Это также имеет место, когда я поворачиваю назад к портрету.

Я попытался использовать setRetainInstance(true); в моем Fragments, но это не сработает.

Есть ли способ, с помощью которого мне нужно переопределить или сделать что-то с моим Fragments перед вращением?

Спасибо заранее.

EDIT Теперь я видел, что onTabSelected вызывается снова, когда активность воссоздана. Может ли это быть причиной моей проблемы с присоединением фрагментов более одного раза?

Вот мои действия onCreate.

super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
           //setContentView(R.layout.main);

        }
     // Create the Action Bar with tabs
        ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        actionBar.setDisplayShowTitleEnabled(false);
        //create the tab for track and add it to the action bar.
        Tab tab = actionBar.newTab()
                            .setText("Track")
                            .setTabListener(new MyTabListener<TrackingFragment>(this,"track",TrackingFragment.class));
        actionBar.addTab(tab);

        //create the tab for ski tracks and add it to the action bar.
        tab = actionBar.newTab()
                        .setText("Something Tracks")
                        .setTabListener(new MyTabListener<TrackListFragment>(this,"somethingtracks",TrackListFragment.class));
        actionBar.addTab(tab);

        //create the tab for photos and add it to the action bar.
        tab = actionBar.newTab()
                        .setText("Photos")
                        .setTabListener(new MyTabListener<PhotoFragment>(this,"photos",PhotoFragment.class));
        actionBar.addTab(tab);
4b9b3361

Ответ 1

Короткое исправление:

В методе onTabSelected перед использованием if (mFragment == null) вам нужно попытаться получить фрагмент (используя mFragment = getSupportFragmentManager().findFragmentByTag(mTag)). Вы также можете установить это извне, но я не вижу, как вы это делаете.

Проверка if(savedInstanceState == null) на onCreate также может решить эту проблему, и я считаю, что это лучший подход!:)

Ответ 2

Похоже, что у вас нет чего-то в вашем методе onCreate, заключенном в if(savedInstanceState == null), поэтому вы создаете еще один фрагмент в дополнение к тому, который был восстановлен из пакета savedInstanceState.

ИЗМЕНИТЬ

Посмотрев более внимательно на свой код, я думаю, что я ошибся в onCreate, ваш onTabSelected должен его обработать. Я думаю, что ваш if (mFragment == null) всегда имеет значение null, потому что вы не пытаетесь найти фрагмент. Измените этот раздел кода на:

@Override 
public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 

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

    if (mFragment == null){ // check to see if the fragment has already been initialised. If not create a new one. 
        mFragment = android.support.v4.app.Fragment.instantiate(mActivity, mClass.getName()); 
        ft.add(android.R.id.content,mFragment,mTag); 
    } else { 
        ft.attach(mFragment); // if the fragment has been initialised attach it to the current activity 
    } 
} 

Ответ 3

Я узнал, что setRetainInstance фактически игнорируется, и все фрагменты, созданные android.support.v4.app.FragmentManager, хранятся в onSaveInstanceState и воссозданы в onCreate.

Для меня решение заключалось в том, чтобы прямо удалить лишний сохраненный фрагмент: fooobar.com/questions/287435/...

Ответ 4

У меня была более или менее та же проблема, но приведенные выше решения, похоже, не работали в моей ситуации. В конце концов я нашел следующее решение:

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    if (mFragment == null) {
        mFragment = Fragment.instantiate(mActivity, mClass.getName());
        ft.replace(android.R.id.content, mFragment, mTag); // Use replace iso add
    }
    else {
        ft.attach(mFragment);
    }
}

Ответ 5

if (savedInstanceState == null) не работает всегда. иногда savedInstanceState!= null, пока вам нужно добавить другой фрагмент из-за ландшафтной ориентации.

Другой подход состоит в том, чтобы проверить, является ли fm.findFragmentById(R.id.frameLayoutLeft), независимо от того, что представляет собой ориентация, ноль или нет, если это так, чем создание нового экземпляра фрагмента, в противном случае ничего не делать. Если вам нужен второй фрагмент в ландшафтном режиме, вам нужно сначала проверить, не ландшафт или нет, если это так, проверьте, является ли fm.findFragmentById(R.id.frameLayoutRight) нулевым или нет. если null, чем create, в противном случае ничего не делать, потому что он уже сохранен ОС Android.