Search code examples
androidandroid-fragmentsmaterial-designandroiddesignsupport

Android: TabLayout not showing any tabs


First time working with com.android.support:design:23.1.1, and having some issues getting TabLayout to work.

My app is basically set up as such:

  • One main activity called LandingActivity which has a DrawerLayout with menu items in it.

  • When selecting a menu item, I load different Fragments into a FrameLayout in the LandingActivity.

  • Some of the loaded Fragments should show tabs at the top, some shouldn't.

My issue is, on the Fragment which is supposed to show tabs at the top, it has extra space in the nav bar like it should have tabs there, but nothing shows.

Code:

activity_landing.xml

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

<!-- This LinearLayout represents the contents of the screen  -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- The ActionBar displayed at the top -->
    <include
        layout="@layout/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <!-- The main content view where fragments are loaded -->
    <FrameLayout
        android:id="@+id/flContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

<!-- The navigation drawer that comes from the left -->
<!-- Note that `android:layout_gravity` needs to be set to 'start' -->
<android.support.design.widget.NavigationView
    android:id="@+id/nvView"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="@android:color/white"
    app:menu="@menu/drawer" />

LandingActivity where I load the fragments:

 public void selectDrawerItem(MenuItem menuItem) {
    // Create a new fragment and specify the planet to show based on
    // position
    Fragment fragment = null;

    switch(menuItem.getItemId()) {
        case R.id.drawer_home:
            fragment = HomeFragment.newInstance();
            break;
        case R.id.drawer_customize:
            fragment = CustomizeFragment.newInstance();
            break;
        default:
            fragment = HomeFragment.newInstance();
    }

    // Insert the fragment by replacing any existing fragment
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();

home_fragment.xml (one which has tabs)

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

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

HomeFragment.java

public class HomeFragment extends Fragment {

public static HomeFragment newInstance() {
    Bundle args = new Bundle(); alreadySelectedFollowingInfo);

    HomeFragment fragment = new HomeFragment();
    fragment.setArguments(args);
    return fragment;
}

public HomeFragment() {

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    final View v = inflater.inflate(R.layout.fragment_home, container, false);

    final TabLayout tabLayout = (TabLayout) v.findViewById(R.id.tabLayout);
    tabLayout.addTab(tabLayout.newTab().setText("One"));
    tabLayout.addTab(tabLayout.newTab().setText("Two"));
    final ViewPager viewPager = (ViewPager) v.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) {

        }
    });

    tabLayout.post(new Runnable() {
        @Override
        public void run() {
            tabLayout.setupWithViewPager(viewPager);
        }
    });

    return inflater.inflate(R.layout.fragment_home, container, false);
}

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:
                BlogFragment tab1 = BlogFragment.newInstance();
                return tab1;
            case 1:
                TrendingFragment tab2 = TrendingFragment.newInstance();
                return tab2;
            default:
                return null;
        }
    }

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

}

Might not be relevant, but tool_bar.xml used in activity_landing.xml

<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="?attr/colorPrimary">

That's about all I've got. Can't figure out what's going on.

What it looks like now

EDIT:

New code:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    final View v = inflater.inflate(R.layout.fragment_home, container, false);



    ViewPager viewPager = (ViewPager) v.findViewById(R.id.viewpager);
    setupViewPager(viewPager);

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



    return v;
}

private void setupViewPager(ViewPager viewPager) {
    PagerAdapter adapter = new PagerAdapter(getFragmentManager());
    adapter.addFragment(BlogFragment.newInstance(), "ONE");
    adapter.addFragment(TrendingFragment.newInstance(), "TWO");
    viewPager.setAdapter(adapter);
}

class PagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public PagerAdapter(FragmentManager manager) {
        super(manager);
    }

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

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

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

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

Solution

  • return inflater.inflate(R.layout.fragment_home, container, false);
    

    in your onCreateView means that you return a newly inflated home fragment without any of your initialization code.

    You should be returning the view that you created at the beginning of onCreateView:

    return v;
    

    Sample PagerAdapter that provides tab titles:

    public class PagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragments = new ArrayList<>();
        private final List<String> mFragmentTitles = new ArrayList<>();
    
        public PagerAdapter(FragmentManager fm) {
            super(fm);
        }
    
        public void addFragment(Fragment fragment, String title) {
            mFragments.add(fragment);
            mFragmentTitles.add(title);
        }
    
        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragments.size();
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitles.get(position);
        }
    }
    

    And so, your refactored onCreateView code would be something like:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    
        View v = inflater.inflate(R.layout.fragment_home, container, false);
    
        final TabLayout tabLayout = (TabLayout) v.findViewById(R.id.tabLayout);
        final ViewPager viewPager = (ViewPager) v.findViewById(R.id.viewpager);
        PagerAdapter adapter = new PagerAdapter(getFragmentManager());
        adapter.addFragment(BlogFragment.newInstance(), "One");
        adapter.addFragment(TrendingFragment.newInstance(), "Two");
    
        viewPager.setAdapter(adapter);
        tabLayout.post(new Runnable() {
            @Override
            public void run() {
                tabLayout.setupWithViewPager(viewPager);
            }
        });
    
    
        return v;
    }