1

I have simple app with fragments.

At the beginning list of fragments is empty.

And there are 2 buttons:

ADD FRAGMENT

REMOVE FRAGMENT

And following use-case:

  1. Add fragment
  2. Add fragment
  3. Remove first fragment
  4. Add fragment

As result onCreateView() on 4th step is not executed.

If I add fragment again on 5th step - onCreateView is executed again.

Why is it so? I didn't find right answer in google.

Source code:

public class MyActivity extends FragmentActivity {

private ViewPager pager;
private FragmentAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    pager = (ViewPager) findViewById(R.id.pager);
    final Button addButton = (Button) findViewById(R.id.add_button);
    addButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            adapter.addFragment(new MyFragment());
            adapter.notifyDataSetChanged();
        }
    });
    final Button removeButton = (Button) findViewById(R.id.remove_button);
    removeButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            adapter.removeFragment(0);
            adapter.notifyDataSetChanged();
        }
    });
    adapter = new FragmentAdapter(getSupportFragmentManager());
    pager.setAdapter(adapter);
    pager.setOffscreenPageLimit(10);
}

private class FragmentAdapter extends FragmentStatePagerAdapter {

    final List<MyFragment> fragments = new ArrayList<MyFragment>();

    public FragmentAdapter(FragmentManager fm) {
        super(fm);
    }

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

    @Override
    public int getCount() {
        return fragments.size();
    }

    public void addFragment(MyFragment fragment) {
        fragments.add(fragment);
    }

    public void removeFragment(int index) {
        fragments.remove(index);
    }

}

private class MyFragment extends Fragment {

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

}

}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
    >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add"
        android:id="@+id/add_button"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Remove first"
        android:id="@+id/remove_button"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

fragment.xml

<?xml version="1.0" encoding="utf-8"?>

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/textView"
        android:layout_gravity="center_horizontal"/>

</LinearLayout>
vetalitet
  • 703
  • 2
  • 10
  • 25

2 Answers2

1

OnCreateView() is only called when the actual Fragment is being drawn on the screen. Since you have removed a fragment at the beginning the pager no longer looks at the same fragment.

To better understand what is going on put a visible number on each of the fragments and then try adding and removing the fragments.

swbandit
  • 1,986
  • 1
  • 26
  • 37
  • hmm. It's really strange. I created 3 fragments dynamically (0, 1, 2). First of all in case of deleting first fragment the last one is deleted (2). And also looks like it's not really removed. It's visible. Not so simple to scroll to see it but anyway it's visible. – vetalitet Jul 03 '14 at 20:05
  • I thought it is like Model-View. I have a model (List of fragments) and a view (pager). And in order to delete fragment I delete it from the model and update the view. But looks like it works in other way. Maybe I need to remove it directly from the View? – vetalitet Jul 03 '14 at 20:07
  • I found this silution, just to use POSITION_NONE all the time in getItemPosition method. http://stackoverflow.com/questions/10396321/remove-fragment-page-from-viewpager-in-android. Looks like it's the only way to solve it. – vetalitet Jul 03 '14 at 20:44
0

The issue is 'FragmentStatePagerAdapter' and the way it's implemented. The way to fix it is this:

  1. Go to googlesource and grab the source for 'FragmentStatePagerAdapter'.
  2. refactor (name, package,etc) to make it your own implementation.
  3. Extend from your NEW version of 'FragmentStatePagerAdapter'
  4. Modify your NEW version of 'FragmentStatePagerAdapter' using these steps below:

a) Change the mFragments.set(index, object) command to mFragments.add(index, object), in the the 'instantiateItem()' function. b) Change the mFragments.set(index, object) command to mFragments.remove(index), in the 'destroyItem' function.

All of this assumes that you are using an ArrayList to hold fragments in your 'extends' class and that they are synced to match the ViewPager.

You will need to add a 'pageIndex' to each fragment, so that you can tell ViewPager when your item has 'moved' (due to deleting an item, that is NOT the LAST item).

This took several days to run down...hope it helps someone :-)