Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ViewPager with multiple fragment instances of same class

I am trying to create a ViewPager which contains 5 fragments. 5 fragments "container", so each of them contain 2 fragments. The 4 first fragments have the same layout and belong to the same class. The fifth is from an other class, and there is no problem with that one.

The problem is that when the activity launches, only 1 fragment seem to be working (the one at position 0 in viewPager). I tried to return new Fragment() at position 0 in my PagerAdapter, but when I do that it's the 2nd fragment that is working. (By working i mean displaying the list on the left, I still haven't taken care of the details fragment on the right)

Here is some code

CustomPagerAdapter.java

public class CustomPagerAdapter extends FragmentPagerAdapter{

public CustomPagerAdapter(FragmentManager fm) {
    super(fm);
}
public CustomPagerAdapter(FragmentManager fm, Context context) {
    super(fm);

}

@Override   
public Fragment getItem(int pos) {

    if(pos == 4)
        return new OtherContainerFragment();
    else
        return new ContainerFragment(pos);

}

@Override
public int getCount() {

    return 5;
}

ContainerFragment.java

public class ContainerFragment extends Fragment {
private int CONTAINER_TYPE;

public ContainerFragment(){

}

public ContainerFragment(int type){
    CONTAINER_TYPE = type;
}



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


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_container, container, false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);


    FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
    CustomListFragment frag = new CustomListFragment(CONTAINER_TYPE);

    ft.replace(R.id.replaceable_list, frag);

    ft.commit();

CustomListFragment.java

public class CustomListFragment extends SuperCustomListFragment{

private ArrayList<Model> mModels;
private int TYPE;


public CustomListFragment(){

}

public CustomListFragment(int type){
    TYPE = type;
}


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


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return super.onCreateView(inflater, container, savedInstanceState);
}


@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    mModels = new ArrayList<Model>();


     if(TYPE == AppConstants.FRAGMENT_TYPE_JOURNAL){
        mAdapter = AppUtils.getJournalListAdapter(getActivity(), mModels);
        new syncPapers().execute();
     }else if(TYPE == AppConstants.FRAGMENT_TYPE_MOVIES){
         mAdapter = AppUtils.getMoviesListAdapter(getActivity(), mModels);
         new syncMovies().execute();
     }


    if(mAdapter != null)
        mListView.setAdapter(mAdapter);  //mListView is defined in the superClass 

Here are the constants I use :

public class AppConstants {


public static final int FRAGMENT_TYPE_AGENDA = 0; //so Fragment at position 0 should be of type agenda
public static final int FRAGMENT_TYPE_NEWS = 1; // position 1 should be of type news
public static final int FRAGMENT_TYPE_MOVIES = 2; // ...
public static final int FRAGMENT_TYPE_JOURNAL = 3; // ...

}

And the xml for the container :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >

<LinearLayout
    android:id="@+id/replaceable_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</LinearLayout>

<LinearLayout
    android:id="@+id/replaceable_details"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:background="@drawable/background" >
</LinearLayout>

</LinearLayout>

SO this code is not working, it seems that the list on the left in the fragment container is replaced in each fragment, and only the fragment at position 0 displays it. (Currently it displays the list with the adapter of type "JOURNAL", but it should display list of type "AGENDA".

-------------------- *BUT !...* --------------------

If I create different fragment_container layout-files, and write IF conditions in the onCreateView and onViewCreated in the ContainerFragment.java, everything works fine. So :

ContainerFragment.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle      savedInstanceState) {
if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_JOURNAL)
    return inflater.inflate(R.layout.fragment_container_journal, container, false);
else if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_MOVIES)
    return inflater.inflater(R.layout.fragment_container_movies, container, false);
else
    return super.onCreateView(LayoutInflater inflater, ViewGroup container, Bundle      savedInstanceState);
}


@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);


    FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
    CustomListFragment frag = new CustomListFragment(CONTAINER_TYPE);

    if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_JOURNAL)
        ft.replace(R.id.replaceable_journal_list, frag);
    else if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_MOVIES)
        ft.replace(R.id.replaceable_movies_list, frag);
    else 
        return;

    ft.commit();

I guess that's because in each fragment, I replace the LinearLayout of the same ID ? (replaceable_list) I thought it was possible to share the same layout file for every fragments and didn't want to create 4 layout-files that would be the same. But it looks like I must do so ? Or am I missing something here ?

Thank you for your time,

like image 970
Seb83 Avatar asked Nov 03 '13 19:11

Seb83


Video Answer


2 Answers

Though a very late response but I was facing same kind of issue and I fixed the issue by using

getChildFragmentManager().beginTransaction()

instead of

getActivity().getSupportFragmentManager().beginTransaction()

As in this case we are trying to make transaction from within a fragment (one out of the list of fragments which are attached to the ViewPager, thus the Activity holding the ViewPager) so we have to use getChildFragmentManager() here for desired results.

like image 143
arorak Avatar answered Sep 23 '22 02:09

arorak


I was able to solve this by setting the id of the layout that is inflated within each fragment to its position.

What you would have to do is simply change the method onCreateView in you ContainerFragment class to:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_container, container, false);
    v.setId(CONTAINER_TYPE)
    return v;

This works because of the way the FragmentPagerAdapter implementation handles fragment tags.

like image 41
Luccas Correa Avatar answered Sep 21 '22 02:09

Luccas Correa