Akshay
Akshay

Reputation: 6142

Tab selector not working on previous tab click when swipe on viewpager

I'm following this example..

I'm having one issue, when I swipe on ViewPager respective fragment appear but when I swipe from from left to right or right to left and select previous Tab the Tab indicator appear on new selected Tab but respective fragment not appear on ViewPager. Please help me, where I'm getting wrong?

Upvotes: 10

Views: 9134

Answers (6)

Aniruddha K.M
Aniruddha K.M

Reputation: 7511

None of the above answers worked for me AS of end of 2016 the bug still exists in design support library 24+. I was able to fix this issue by wrapping the tab layout inside a
co-ordinator layout

Upvotes: 2

Moinkhan
Moinkhan

Reputation: 12932

It was bug in support lib 23.0.0 but it is solved in 23.0.1. First of all update your suppory library using SDK manager from the extras section. and write the following line in app gradle file.

compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.android.support:design:23.0.1'

for your reference

https://developer.android.com/topic/libraries/support-library/revisions.html and read the Changes for Design Support library in Android Support Library, revision 23.0.1 section

Upvotes: 5

Vaibhav Gupta
Vaibhav Gupta

Reputation: 401

Are you using support library version 23.0.0. There was an issue https://code.google.com/p/android/issues/detail?id=183123 which looks similar to yours. If that is the case indeed, update your support library version to 23.0.1. This issue has been fixed.

Upvotes: 0

Hong Thai
Hong Thai

Reputation: 218

In your activity, after find Views by Id, you should "config" your ViewPager and TabLayout. Some necessary features maybe: "addOnPageChangeListener" for ViewPager and "setOnTabSelectedListener" for your TabLayout like this:

public class MainActivity extends AppCompatActivity {

private final int numOfPages = 4; //viewpager has 4 pages
private final String[] pageTitle = {"Food", "Movie", "Shopping", "Travel"};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    for (int i = 0; i < numOfPages; i++) {
        tabLayout.addTab(tabLayout.newTab().setText(pageTitle[i]));
    }

    //set gravity for tab bar
    tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);

    final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
    final PagerAdapter adapter = new PagerAdapter
            (getSupportFragmentManager(), numOfPages);

    viewPager.setAdapter(adapter);
    viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
    tabLayout.setOnTabSelectedListener(onTabSelectedListener(viewPager));
}

private TabLayout.OnTabSelectedListener onTabSelectedListener(final ViewPager pager) {
    return new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            pager.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    };
}

I have a tutorial post about this and it works well! There is no error like yours. Hope it help: http://www.devexchanges.info/2015/08/android-material-design-viewpager-with.html

Upvotes: 4

ultraon
ultraon

Reputation: 2400

I have more shorter variant to fix this bug (android support design lib v.23.0.0):

...
//initialize views
    mViewPager.setAdapter(pagerAdapter);
    mTabLayout.setupWithViewPager(mViewPager);
    mViewPager.clearOnPageChangeListeners();
    mViewPager.addOnPageChangeListener(new WorkaroundTabLayoutOnPageChangeListener(mTabLayout));
...

And class WorkaroundTabLayoutOnPageChangeListener:

public class WorkaroundTabLayoutOnPageChangeListener extends TabLayout.TabLayoutOnPageChangeListener {
    private final WeakReference<TabLayout> mTabLayoutRef;

    public WorkaroundTabLayoutOnPageChangeListener(TabLayout tabLayout) {
        super(tabLayout);
        this.mTabLayoutRef = new WeakReference<>(tabLayout);
    }

    @Override
    public void onPageSelected(int position) {
        super.onPageSelected(position);
        final TabLayout tabLayout = mTabLayoutRef.get();
        if (tabLayout != null) {
            final TabLayout.Tab tab = tabLayout.getTabAt(position);
            if (tab != null) {
                tab.select();
            }
        }
    }
}

Upvotes: 0

Gatunox
Gatunox

Reputation: 532

This is what i use and works fine.

Adapter:

    public class SCFragmentPagerAdapter extends FragmentPagerAdapter {

    private final List<Fragment> mFragments = new ArrayList<>();
    private final List<String> mFragmentTitles = new ArrayList<>();

    private Context mContext;
    private FragmentManager mFragmentManager;

    public SCFragmentPagerAdapter(FragmentManager fm, Context context) {
        super(fm);
        this.mFragmentManager = fm;
        this.mContext = context;
    }

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

    // Return the correct Fragment based on index
    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    public void addFragment(Fragment fragment, String title) {
        mFragments.add(fragment);
        mFragmentTitles.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        // Return the tab title to SlidingTabLayout
        return mFragmentTitles.get(position);
    }


    public Fragment getActiveFragment(ViewPager container, int position) {
        String name = makeFragmentName(container.getId(), position);
        return  mFragmentManager.findFragmentByTag(name);
    }

    private static String makeFragmentName(int viewId, int index) {
        return "android:switcher:" + viewId + ":" + index;
    }

}

Activity:

public class SCWelcomeActivity extends AppCompatActivity implements
        SCWelcomeFragment.OnFragmentInteractionListener,
        SCSyncFragment.OnFragmentInteractionListener,
        SCRegisterFragment.OnFragmentInteractionListener,
        SCConfirmationFragment.OnFragmentInteractionListener {

    private static final String TAG = SCWelcomeActivity.class.getSimpleName();

    private ViewPager viewPager = null;
    private TabLayout tabLayout = null;
    private Toolbar toolbar = null;
    private SCFragmentPagerAdapter adapter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scwelcome);

        // Layout manager that allows the user to flip through the pages
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        // Initialize the Sliding Tab Layout
        tabLayout = (TabLayout) findViewById(R.id.tablayout);

        // Connect the viewPager with the sliding tab layout
        tabLayout.setupWithViewPager(viewPager);
        tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

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

    @Override
    public void onFragmentInteraction(Uri uri) {

    }


    private void setupViewPager(ViewPager viewPager) {

        adapter = new SCFragmentPagerAdapter(getSupportFragmentManager(), SCWelcomeActivity.this);
        adapter.addFragment(SCWelcomeFragment.newInstance(), getString(R.string.title_tab1));
        adapter.addFragment(SCSyncFragment.newInstance(), getString(R.string.title_tab2));
        adapter.addFragment(SCRegisterFragment.newInstance(), getString(R.string.title_tab3));
        adapter.addFragment(SCConfirmationFragment.newInstance(), getString(R.string.title_tab4));


        viewPager.setAdapter(adapter);
        viewPager.setOffscreenPageLimit(4);
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }
}

Fragment Example :

    public class SCWelcomeFragment extends Fragment {

    private OnFragmentInteractionListener mListener;

    public static SCWelcomeFragment newInstance() {
        SCWelcomeFragment fragment = new SCWelcomeFragment();
        return fragment;
    }

    public SCWelcomeFragment() {
        super();
    }

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

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }
}

Layout:

    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="130dp"
        android:fitsSystemWindows="true"
        android:gravity="bottom"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin"
            android:layout_gravity="center"
            android:theme="@style/ThemeOverlay.AppCompat.Dark"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tablayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />


    </android.support.design.widget.AppBarLayout>


</android.support.design.widget.CoordinatorLayout>

Please try to implement the adapter as i do. Pay close attention that in mine Adapter all instances are saved in the

private final List<Fragment> mFragments = new ArrayList<>();

In your case you are always returning a new instance. So that's why a set the setOffscreenPageLimit(4). to 4 so they are kept in memory as well.

Upvotes: 4

Related Questions