Вкладки Android, реализованные с помощью Fragments и ViewPager

В моем приложении есть 3 вкладки, каждая из которых представлена ​​Fragments. Существует пользовательский FragmentPagerAdapter, который также реализует ActionBar.TabListener. Изначально мой FragmentPagerAdapter возвращал новые экземпляры фрагментов в методе public Fragment getItem(int index). Кроме того, моя реализация TabListener создавала фрагменты и отображала/прятала их в файле onTabSelected/onTabUnselected. К сожалению, этот подход мне не подходит, потому что в этом случае каждый фрагмент фактически создается дважды. Я хочу создать его один раз, а затем просто скрыть/показать, когда это необходимо.

Для этого я создал экземпляр своего фрагмента ранее в действии и передал его PagerAdapter:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_tabs_layout);

        List<Fragment> fragments = initTabFragments();

        ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
        final ActionBar actionBar = getSupportActionBar();
        TabsPagerAdapter pagerAdapter = new TabsPagerAdapter(this, getSupportFragmentManager(), fragments, viewPager);

        viewPager.setAdapter(pagerAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);        

        for (int tab_name : tabs) {
            Tab tab = actionBar.newTab();
        actionBar.addTab(tab.setText(tab_name).setTabListener(pagerAdapter));
        }
...
    }

    private List<Fragment> initTabFragments() {
    List<Fragment> fragments = new ArrayList<Fragment>(3);
    fragments.add(SherlockFragment.instantiate(this, TabFragment1.class.getName()));
    fragments.add(SherlockFragment.instantiate(this, TabFragment2.class.getName()));
    fragments.add(SherlockFragment.instantiate(this, TabFragment3.class.getName()));
    return fragments;
    }

Затем в PagerAdapter я просто возвращаю фрагмент:

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

Для обработки выбора Tab существует следующий код:

@Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
int position = tab.getPosition();
    String tag = "android:switcher:" + viewPagerId + ":" + position;
    Fragment fragment = context.getSupportFragmentManager().findFragmentByTag(tag);
    switch (position) {
        case 0:
        if (fragment == null) {
            ft.add(viewPagerId, fragments.get(0), tag);
        } else {
            // If it exists, simply attach it in order to show it
            ft.show(fragments.get(0));
        }
        break;
        }
        case 1:
            if (fragment == null) {
                ft.add(viewPagerId, fragments.get(1), tag);
            } else {
                // If it exists, simply attach it in order to show it
                ft.show(fragments.get(1));
            }
            break;
            }

    }

 @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    switch (tab.getPosition()) {
        case 0:
        ft.hide(fragments.get(0));
        break;
        case 1:
        ft.hide(fragments.get(1));
        break;
        }
}

В этом случае каждый фрагмент создается один раз. И первая вкладка отображается правильно, но когда я переключаюсь между вкладками, вторая и третья вкладки пусты (просто белый фон). Почему?

Я пытался добавить фрагмент в контейнер android.R.id.content, но было выдано исключение: Can't change container ID of fragment.... Я узнал, что это потому, что когда Fragment возвращается в методе getItem, он добавляется в контейнер viewPager. Вот почему я использую viewPagerId при добавлении фрагмента в транзакцию.

Любая помощь будет принята с благодарностью.


person Alex K.    schedule 26.12.2013    source источник


Ответы (1)


Определите класс ExampleFragment, который расширяет Fragment. Что-то вроде показанного ниже

public class ExampleFragment extends Fragment {

    private View categoryView;
    private ViewPager mViewPager;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        categoryView = inflater.inflate(R.layout.viewpager, container, false);
        mViewPager = (ViewPager) categoryView.findViewById(R.id.pager);
        return categoryView;
    }

    public ViewPager returnViewPager() {
        return mViewPager;
    }
}

main_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    tools:context=".ExampleFragmentActivity" >

    <fragment
        android:id="@+id/main_fragment"
        android:name="somepackage.ExampleFragment"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

А затем добавьте это в onCreate() объекта ExampleFragmentActivity.

ExampleFragment fragment = (ExampleFragment) getSupportFragmentManager().findFragmentById(R.id.main_fragment);
mViewPager = fragment.returnViewPager();

fragmentManager = getSupportFragmentManager();
person VikramV    schedule 26.12.2013
comment
Спасибо за ответ, но зачем мне раздувать макет viepager во Фрагменте, который на самом деле должен содержать представление списка? - person Alex K.; 26.12.2013