Using TabLayout inside a Fragment; tab text invisible
Asked Answered
B

5

22

I'm currently experimenting with various new components in the new Android Support Design library. I've implemented a NavigationView in my MainActivity.java, which uses a FragmentManager to navigate between the items in the Navigation drawer:

getSupportFragmentManager()
    .beginTransaction()
    .replace(R.id.content, mTabLayoutFragment)
    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
    .commit();

I'm using a TabLayout in one of the fragments. Here is the fragment's layout:

<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed"
        app:tabGravity="fill"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"/>

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

And the Java code behind it:

import android.os.Bundle;
import android.support.design.widget.*;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class TabLayoutFragment extends Fragment {   


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View inflatedView = inflater.inflate(R.layout.fragment_tablayout, container, false);

        TabLayout tabLayout = (TabLayout) inflatedView.findViewById(R.id.tabLayout);
        tabLayout.addTab(tabLayout.newTab().setText("Campusplan"));
        tabLayout.addTab(tabLayout.newTab().setText("Raumplan"));
        final ViewPager viewPager = (ViewPager) inflatedView.findViewById(R.id.viewpager);

        viewPager.setAdapter(new PagerAdapter
                (getFragmentManager(), tabLayout.getTabCount()));
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager.setCurrentItem(tab.getPosition());
            }

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

            }

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

            }
        });

        return inflatedView;
    }

    public class PagerAdapter extends FragmentStatePagerAdapter {
        int mNumOfTabs;

        public PagerAdapter(FragmentManager fm, int NumOfTabs) {
            super(fm);
            this.mNumOfTabs = NumOfTabs;
        }

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    TabItem1 tab1 = new TabItem1();
                    return tab1;
                case 1:
                    TabItem1 tab2 = new TabItem1();
                    return tab2;
                default:
                    return null;
            }
        }

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

Please note TabItem1 and TabItem1, which are fragments consisting of nothing but a TextView. These two are to be displayed in the TabLayout.

Now, this code seems to be working, to some extent. Here is how it looks like:

What's weird is, after I rotate the device, everything seems to be working just fine:

enter image description here

It seems like something gets called upon a configuration change. This is weird, especially considering that I have following in my AndroidManifest:

android:configChanges="orientation|screenSize"
Boyne answered 26/7, 2015 at 21:9 Comment(1)
Update: This was due to a bug in the design library 22.2.1. Using 23.0.0 solves this.Schlock
B
35

I face the same problem with new version of android support Design Library v23.1.1. But I just figure it out what happening.

if your view pager has 2 fragment as your mention above, then you set your view pager with this statement:

tabLayout.setupWithViewPager(viewPager);

automatically you will have 2 tabs with empty text. So you should not add new tab anymore. But something you have to do is to set text in that two created tabs.

tabLayout.getTabAt(0).setText("Campusplan");
tabLayout.getTabAt(1).setText("Raumplan");

Conclusion. To make tabs work as you want, important thing you have to do :

tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setText("Campusplan");
tabLayout.getTabAt(1).setText("Raumplan");

I hope this will be helpful for you :)

Bedding answered 7/12, 2015 at 9:53 Comment(3)
This is correct answear for me. As mentioned above works for support Design Library 23.1.1. Thank you:)Lassitude
but why this will not work?tabLayout.addTab(tabLayout.newTab().setText("Campusplan")); tabLayout.addTab(tabLayout.newTab().setText("Raumplan"));Gyroplane
@Gyroplane as far as I know, like my explanation above. When you set viewpager inside tabLayout, the tablayout automatically add a number of tabs depends on number of viewpager's fragment you have. So when you use this statememnt: tabLayout.addTab(tabLayout.newTab().setText("Campusplan")); you add a new tab with empty fragment. CMIIWBedding
B
19

Update: Design Library v23.0.0 solves this issue.


Found the problem here: https://code.google.com/p/android/issues/detail?id=180462

Simple workaround:

tabLayout.post(new Runnable() {
    @Override
    public void run() {
        tabLayout.setupWithViewPager(viewPager);
    }
});
Boyne answered 26/7, 2015 at 22:52 Comment(4)
The tabs now are ok, but sometimes when I change between the Navigation drawer items, the inner fragment of this TabLayout disappear. Do you have your code on github to look at?Hyperextension
thank you, I was using getActivity().getSupportFragment() instead of getChildFragmentManager()Hyperextension
compiling design library v23.0.1 made me gradle execution error with empty error message, but the code workaroud working fine, thanks.Maggs
Is it recommended that we put the ViewPager inside an AppBarLayout if we are working with a TabLayout attached to our Toolbar or it doesn't matter where you put the viewpager in the xml layouts?Cayuga
W
5

just tried to override the method in adapter:

public CharSequence getPageTitle(int position) {}

and it works.

Wavelength answered 28/7, 2016 at 10:2 Comment(0)
S
2

The developer working on this library recommends the following work-a-round:

if (ViewCompat.isLaidOut(tabLayout)) {
        tabLayout.setupWithViewPager(viewPager);
    } else {
        tabLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                tabLayout.setupWithViewPager(viewPager);
                tabLayout.removeOnLayoutChangeListener(this);
            }
        });
    }
Shawntashawwal answered 10/8, 2015 at 13:13 Comment(0)
C
1

Lack reputation to comment @arif ardiansyah...

Check the source code:

 `TabLayout#setupWithViewPager(...)` 

 -->>`setPagerAdapter(adapter, true);`

 -->>`populateFromPagerAdapter();`

Here, TabLayout removes all tabs and recreates some new tabs whose text are set with PagerAdapter#getPageTitle(...). So you can override this method to provide Tablayout with your tabs' title.

Concent answered 27/7, 2016 at 10:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.