user1301593 user1301593 - 1 month ago 32
Android Question

Infinite ViewPager with TabLayout

I've implemented an infinite ViewPager in situ https://github.com/JoachimR/AnyDayViewPager. However, instead of using a PagerTabStrip, I'd prefer to use a CoordinatorLayout with TabLayout. But when setting up the TabLayout with the viewpager, (I'm assuming because there are an "infinite number of ViewPager Fragments") the app gets stuck.

How can I solve this issue?

Here's the code
(the other files which I have not changed can be found at JoachimR/AnyDayViewPager, e.g., FragmentContent.java, CachingFragmentStatePagerAdapter.java, TimeUtils.java, etc)

MainActivity.java

import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.support.design.widget.TabLayout;
import android.os.Bundle;

import java.util.Calendar;

public class MainActivity extends FragmentActivity {

private static Context mContext;

private CachingFragmentStatePagerAdapter adapterViewPager;


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

mContext = this;

ViewPager vpPager = (ViewPager) findViewById(R.id.vpPager);
adapterViewPager = new MyPagerAdapter(getSupportFragmentManager());
vpPager.setAdapter(adapterViewPager);

// set pager to current date
vpPager.setCurrentItem(TimeUtils.getPositionForDay(Calendar.getInstance()));

/** THIS IS WHERE THE ISSUES ARISE **/
TabLayout tabLayoutDiary = (TabLayout) findViewById(R.id.diary_tabs);
tabLayoutDiary.setupWithViewPager(vpPager);

}

public static class MyPagerAdapter extends CachingFragmentStatePagerAdapter {

private Calendar cal;

public MyPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}

@Override
public int getCount() {
return TimeUtils.DAYS_OF_TIME;
}

@Override
public Fragment getItem(int position) {
long timeForPosition = TimeUtils.getDayForPosition(position).getTimeInMillis();
return FragmentContent.newInstance(timeForPosition);
}

@Override
public CharSequence getPageTitle(int position) {
Calendar cal = TimeUtils.getDayForPosition(position);
return TimeUtils.getFormattedDate(mContext, cal.getTimeInMillis());
}


}

}


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:fab="http://schemas.android.com/tools">

<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.TabLayout
android:id="@+id/diary_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/vpPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

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

Answer

Possibly due to this bug: https://code.google.com/p/android/issues/detail?id=180027

TabLayout creates a TextView tab for each page in your ViewPager, rather than dynamically creating and recycling the TextViews. As you're seeing, this will just blow up if you try to fake out an infinite ViewPager.

Unfortunately, there's no fix for now. You can try using https://github.com/nshmura/RecyclerTabLayout which was linked on the bug, but I've not used it myself.