Невозможно изменить идентификатор контейнера фрагмента

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

У меня проблема в том, что в портретной ориентации мое представление заполняется ViewPager, а также двумя важными фрагментами и их данными в его адаптере. В альбомной ориентации представление заполняется теми же двумя фрагментами, но рядом в одном макете, а не в ViewPager. Я сохраняю фрагменты в onSaveInstanceState и снова извлекаю их следующим образом:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    if (mSummaryFragment != null) {
        getFragmentManager().putFragment(outState, TAG_SUMMARY, mSummaryFragment);
    }

    if (mDetailsFragment != null) {
        getFragmentManager().putFragment(outState, TAG_DETAILS, mDetailsFragment);
    }
}

Получение в onCreate...

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

    if (savedInstanceState != null) {
        mSummaryFragment = (SummaryFragment) getFragmentManager().getFragment(savedInstanceState, TAG_SUMMARY);
        mDetailsFragment = (DetailsFragment) getFragmentManager().getFragment(savedInstanceState, TAG_DETAILS);
    } else {
        mSummaryFragment = new SummaryFragment();
        mDetailsFragment = new DetailsFragment();
    }
}

Я должен упомянуть, что эти фрагменты являются вложенными, потому что моя основная деятельность на самом деле является самим фрагментом. Начиная с 4.2, я считаю, что это не должно быть проблемой, но я не на 100% разбираюсь в жизненном цикле. Мое представление заполняется следующим образом:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    setHasOptionsMenu(true);

    View result = inflater.inflate(R.layout.main, container, false);
    ViewPager pager = (ViewPager) result.findViewById(R.id.viewpager);
    if (null != pager) {
        pager.setAdapter(new PagerAdapter(getFragmentManager(), mUpdater));
    } else {
        FragmentManager fm = getFragmentManager();
        fm.beginTransaction().add(R.id.summary_container, mSummaryFragment).commit();
        fm.beginTransaction().add(R.id.details_container, mDetailsFragment).commit();
    }

    if (savedInstanceState == null) {
        Refresh(0,0);
    }

    return (result);
}

Метод getItem PagerAdapter выглядит следующим образом:

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return mSummaryFragment;

            case 1:
                return mDetailsFragment;
        }
        return null;
    }

При первом запуске все работает нормально, но когда ориентация меняется, я получаю эту ошибку в logcat независимо от того, как меняется ориентация (книжная -> альбомная или наоборот):

java.lang.IllegalStateException: невозможно изменить идентификатор контейнера фрагмента. SummaryFragment{40dd1800 #1 id=0x7f0b004a android:switcher:2131427400:0}: было 2131427402, теперь 2131427400

Я не совсем уверен, что это лучший способ сделать то, что я хочу, однако сохранение фрагментов в пакет и их извлечение было уловкой, которую я заметил в исходном коде Google IO 2013, поэтому я надеюсь, что это хотя бы частично верно.


person Karl    schedule 12.08.2013    source источник
comment
stackoverflow.com/questions/9906254 /   -  person Arash GM    schedule 12.08.2013


Ответы (2)


Я нашел решение. Для портретного и ландшафтного режимов я использую ViewPager, но я переопределяю метод адаптера страницы:

публичный float getPageWidth (целая позиция)

В нормальном состоянии этот метод возвращает 1.0f, а ViewPager показывает одну страницу, а когда метод возвращает 0.5f - две страницы. В портретном режиме установите PAGE_WIDTH_FULL_SCREEN, а в альбомном PAGE_WIDTH_HALF_SCREEN при создании адаптера в действии. Пример кода с переопределенными общедоступными методами ниже:

public class ViewPagerAdapter extends FragmentPagerAdapter {

public static final float PAGE_WIDTH_FULL_SCREEN = 1.0f;
public static final float PAGE_WIDTH_HALF_SCREEN = 0.5f;

private FragmentManager fragmentManager;
private ArrayList<Fragment> fragments;
private float pageWidth = PAGE_WIDTH_FULL_SCREEN;

public ViewPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments) {
    super(fm);
    this.fragmentManager = fm;
    this.fragments = fragments;
}

public void setPageWidth(float pageWidth) {
    this.pageWidth = pageWidth;
}

@Override
public float getPageWidth(int position) {
    return pageWidth;
}

@Override
public Fragment getItem(int position) {
    return fragments.get(position);
}

@Override
public int getCount() {
    return fragments.size();
}
}
person Pavel Shysh    schedule 07.11.2013

Сначала вам нужно удалить его.

if (null != pager) {
    pager.setAdapter(new PagerAdapter(getFragmentManager(), mUpdater));
} else {
    FragmentManager fm = getFragmentManager();
    fm.beginTransaction().remove(mSummaryFragment).add(R.id.summary_container, mSummaryFragment).commit();
    fm.beginTransaction().remove(mDetailsFragment).add(R.id.details_container, mDetailsFragment).commit();
}
person Jon    schedule 12.08.2013