Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ViewPager first fragment shown is always wrong with FragmentStatePager

I am trying to have the same view pager + tabs design as the PlayStore 5.1.x. Here is my layout :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center_vertical|center_horizontal"
    android:gravity="center_vertical|center_horizontal"
    android:orientation="vertical">

    <com.astuetz.PagerSlidingTabStrip
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@drawable/background_tabs" />

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

</LinearLayout>

My Adapter:

public class MainPagerAdapter extends FragmentStatePagerAdapter {

    private ArrayList<FakeFragment> fragments;

    public MainPagerAdapter(FragmentManager fm) {
        super(fm);
        // TODO Auto-generated constructor stub
        fragments = new ArrayList<FakeFragment>();
    }

    @Override
    public Fragment getItem(int position) {
        // TODO Auto-generated method stub      
        if(position < getCount()) {
            FakeFragment fragment = FakeFragment.newInstance(position);
            fragments.add(fragment);
        }
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return Category.values().length;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        // TODO Auto-generated method stub
        return Category.values()[position].getTitle();
    }

    @Override
    public int getItemPosition(Object object) {
        // TODO Auto-generated method stub
        return POSITION_NONE;
    }
}

My tabs and pager are showing correctly ! but i have noticed that the first fragment shown in the view pager is always the same as the second one. Then when I swipe once, twice and swipe back to the first page, I find that the correct fragment is now shown !!

I can't understand why this behaviour, please I need some explanations.

SOLUTION

The issue was due to my FakeFragment.newInstance() method definition.

private static int position;

public static FakeFragment newInstance(int position) {
    // TODO Auto-generated method stub
    FakeFragment.position = position;
    return new FakeFragment();
}

I changed it by using a setArguments(args) to my FakeFragment instance, and then retrieve it in onCreate method. Now all is working nice !

Can somebody explain me why ??

I think that, in this way, value of position will entierly depend on fragment's lifecycle, so will be always the expected position, Right ??

like image 484
S.Thiongane Avatar asked Dec 27 '14 22:12

S.Thiongane


1 Answers

1) Do not implement getItemPosition(Object) if you don't handle it. You're not required to implement it and you might break some other functionality by implementing it wrong.

2) The point of getItem(int) is to return a new fragment. Ditch the fragment array as it makes no sense.

3) Make the adpater class static (It promotes reusability, the adapter should not depend on the parent class to get its data set, right?) and pass the Categorys as a constructor parameter. Store it in a variable and make new fragments according to this data set. You'll also probably want to pass a Category[position] as a parameter to the fragment constructor instead of just position.

like image 182
Eugen Pechanec Avatar answered Oct 16 '22 08:10

Eugen Pechanec