0

I try to populate a TabLayout with a ViewPager but unfortunately it doesn't get populated.

I followed this tutorial to get in touch: TabLayout and ViewPager in your Android App. The tutorial uses the old Support Library v4. My project is based on AndroidX and i want to stay with it. The official documentation of TabLayout said that I need to create the TabLayout inside the ViewPager but that's not working at all. So i created the following XML layout file:

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


    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/primaryColor"
            app:tabGravity="fill"
            app:tabMode="fixed"
            app:tabTextColor="@color/primaryTextColor" />

    </androidx.viewpager.widget.ViewPager>

</LinearLayout>

I setup the ViewPager with the following lines to connect TabLayout with ViewPager:

public class MyActivity extends AppCompatActivity {
    ...
    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_layout);
        ...
        // tab layout
        ViewPager viewPager = findViewById(R.id.viewpager);
        MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(this, getSupportFragmentManager());
        viewPager.setAdapter(adapter);
        TabLayout tabLayout = findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);
        ...
    }
    ...
}

My Adapter is a FragmentPagerAdapter

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    private Context context;

    public MyFragmentPagerAdapter(Context context, FragmentManager fm) {
        super(fm);
        this.context = context;
    }

    @Override
    public Fragment getItem(int position) {
        if (position == 0) {
            return new MyFragment1();
        } else {
            return new MyFragment2();
        }
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return context.getString(R.string.building);
            case 1:
                return context.getString(R.string.buff);
            default:
                return null;
        }
    }
}

One of my Fragments looks like this:

public class MyFragment1 extends Fragment {

    public MyFragment () {
        // Required empty public constructor
    }

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

}

Here is a picture how it looks like:

Empty ViewPager

Question

So why is the TabLayout not populated at all? I'm working with Android Studio and the Design Manager just shows me an empty TabLayout and ViewPager. I guess, it would precompile the TabLayout but it is just empty...

Please help me because i stuck at this topic. I really want to code it like this to get benefit of swiping tabs and stuff.

Thanks a lot!

Lecram
  • 60
  • 2
  • 11

4 Answers4

2

Here is an example from one of my projects .Create and populate ViewPager, something like this:

 <androidx.viewpager.widget.ViewPager
    android:id="@+id/loginViewPager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toBottomOf="@id/loginTitle">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/loginTabContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        app:tabIndicatorColor="@color/colorPrimary"
        app:tabRippleColor="@color/colorPrimary"
        app:tabSelectedTextColor="@color/colorPrimaryDark"
        app:tabTextAppearance="@style/TabLayoutTheme">

        <com.google.android.material.tabs.TabItem android:text="first tab" />
        <com.google.android.material.tabs.TabItem android:text="second tab" />

    </com.google.android.material.tabs.TabLayout>
</androidx.viewpager.widget.ViewPager>

Then in your activity create a FragmentStatePagerAdapter to decide what to return in each page. my codes are in kotlin, but java version is the same:

    private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
    override fun getCount(): Int = NUM_PAGES
    override fun getItem(position: Int): Fragment = when (position) {
        1 -> FirstFragment()
        0 -> SecondFragment()
        else -> FirstFragment()
    }

    override fun getPageTitle(position: Int): CharSequence? {
        return when (position) {
            0 -> "First Title"
            1 -> "Second Title"
            else -> "First Title"
        }
    }
}

And finally in your Activity:

    val pagerAdapter = ScreenSlidePagerAdapter(supportFragmentManager)
    loginViewPager.adapter = pagerAdapter
Payam Asefi
  • 2,677
  • 2
  • 15
  • 26
1
  1. Put your TabLayout inside your ViewPager like below.
<androidx.viewpager.widget.ViewPager
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
        <com.google.android.material.tabs.TabLayout xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabBackground="@color/colorPrimaryDark"
        app:tabGravity="fill"
        app:tabIndicatorColor="@color/colorPrimaryLight"
        app:tabMaxWidth="0dp"
        app:tabMode="scrollable"
        app:tabRippleColor="@color/colorPrimaryLight"
        app:tabSelectedTextColor="@color/colorPrimaryLight"
        app:tabTextColor="@android:color/white" />
</androidx.viewpager.widget.ViewPager>

make sure that android:layout_height of your TabLayout is set to wrap_content.

  1. When you put your TabLayout inside your ViewPager, you don't need to keep below lines:

    TabLayout tabLayout = findViewById(R.id.tab_layout);
    tabLayout.setupWithViewPager(viewPager);
    
  2. Everything else in your code is correct.

  3. Also, now that I see your code, layout_height of your TabLayout is set to match_parent, so TabLayout is taking whole space in your screen, giving no height to ViewPager, also, in your XML, there is no container to hold your ViewPager and TabLayout (like LinearLayout, FrameLayout etc).

Vedprakash Wagh
  • 3,595
  • 3
  • 12
  • 33
0
<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">

<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/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="scrollable"
        app:tabGravity="fill"
        style="@style/Base.Widget.Design.TabLayout"/>
</android.support.design.widget.AppBarLayout>

<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"  />

viewPager = (ViewPager)rootView. findViewById(R.id.viewpager);
  ViewPagerAdapter adapter = new ViewPagerAdapter(getFragmentManager());
    adapter.addFragment(new FragAllONE(), "ONE");
    adapter.addFragment(new FragAllTWO(), "TWO");
    viewPager.setAdapter(adapter);
    viewPager.setOffscreenPageLimit(1);
    viewPager.setCurrentItem(0);
    viewPager.addOnPageChangeListener(this);

    tabLayout = (TabLayout)rootView. findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);

private class ViewPagerAdapter extends FragmentStatePagerAdapter {

    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

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

    @Override
    public Fragment getItem(int position) {
  return mFragmentList.get(position)
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }

    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object object = super.instantiateItem(container, position);
        if (object instanceof Fragment) {
            Fragment fragment = (Fragment) object;
            String tag = fragment.getTag();

        }
        return object;
    }

    public void restoreState(Parcelable state, ClassLoader loader) {

    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

}
Nupur
  • 31
  • 4
0

I found a solution on another thread Use Tab layout in MVVM architecture with the data binding library. I'm using Android Data Binding so the TabLayout wasn't assigned to the ViewPager. So my code was correct but not accordingly to the Data Binding.

Nevertheless, thanks for your posts here!

Lecram
  • 60
  • 2
  • 11