3

I can't get this to work. The basic app functions as it's supposed to but the ViewPager on one of the layout files doesn't show any fragment at all. I checked the code multiple times but I can't find a bug. When I tried debugging it I noticed that it doesn't even initialize the fragments classes which it's supposed to when you select a tab. My MainActivity:

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {

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

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    new GetData(this).execute();

    TabLayout tab_layout = (TabLayout) findViewById(R.id.tab_layout);
    tab_layout.addTab(tab_layout.newTab().setText("CASUAL"));
    tab_layout.addTab(tab_layout.newTab().setText("RANKED"));
    tab_layout.setTabGravity(TabLayout.GRAVITY_FILL);

    final ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
    PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), tab_layout.getTabCount());
    viewPager.setAdapter(adapter);
    tab_layout.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) {

        }
    });

}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_stats) {
        // Handle the camera action
    } else if (id == R.id.nav_about) {

    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}
}

My PagerAdapter:

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:
            CasualStats tab1 = new CasualStats();
            return tab1;
        case 1:
            RankedStats tab2 = new RankedStats();
            return tab2;
        default:
            return null;
        }
     }

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

Layout with the ViewPager:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"><![CDATA[

        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_below="@id/tab_layout"/>
]]>

<android.support.design.widget.TabLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_alignParentStart="true"
    android:id="@+id/tab_layout">

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

<view
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    class="android.support.v4.view.ViewPager"
    android:layout_alignParentStart="true"
    android:id="@+id/view_pager"
    android:layout_below="@+id/tab_layout" />

</RelativeLayout>

The classes for the tab fragments which are supposed to be displayed in the ViewPager are just normal auto generated Android Studio fragment classes.

One of the fragments:

public class CasualStats extends Fragment{
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

private OnFragmentInteractionListener mListener;

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

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param param1 Parameter 1.
 * @param param2 Parameter 2.
 * @return A new instance of fragment CasualStats.
 */
// TODO: Rename and change types and number of parameters
public static CasualStats newInstance(String param1, String param2) {
    CasualStats fragment = new CasualStats();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_casual_stats, container, false);
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

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

/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 * <p>
 * See the Android Training lesson <a href=
 * "http://developer.android.com/training/basics/fragments/communicating.html"
 * >Communicating with Other Fragments</a> for more information.
 */
public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}
}

The xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.app.anzel.r6s.CasualStats">

<!-- TODO: Update blank fragment layout -->

<TextView
    android:text="1st fragment"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_alignParentStart="true"
    android:layout_marginStart="28dp"
    android:layout_marginTop="22dp"
    android:id="@+id/textView"
    android:visibility="visible" />
</RelativeLayout>
Tachanka
  • 53
  • 1
  • 8
  • try like this: 1. create adapter for your viewpager. 2. set adapter on your view pager. 3. use tabLayout.setupWithViewPager(your_viewpager); 4. Make sure to use getSupportFragmentManager or getchildFragmentManager(), if the viewpager is in Activity or inside another fragment resp. 5. Your adapter must override public CharSequence getPageTitle(int position) to provide title for each fragment to the tab layout. – Rahul Shukla Jan 13 '17 at 17:03
  • have you tried making sure the fragments are really not visible? I mean you don't seem to be putting anything inside the textview, try changing background or setting some text inside the textview just to test. – Rahul Shukla Jan 13 '17 at 17:17
  • Changed the background color for the fragment but it doesn't display it. – Tachanka Jan 13 '17 at 17:21

6 Answers6

22

The problem is that you have nested fragments and use getFragmentManager(); You should use getChildFragmentManager() instead.

java:

viewPagerAdapter = new PagerAdapter(getChildFragmentManager())

kotlin:

viewPagerAdapter = PagerAdapter(childFragmentManager)
Rasoul Miri
  • 5,433
  • 43
  • 52
  • 1
    Yep. That was exactly my problem. Using the parent FragmentManager, it was fetching previously used Fragment instead of recreating them. In any way, it didn't work. Using getChildFragmentManager create a per-fragment FragmentManager, which solves this. – Rewieer Feb 05 '19 at 10:35
  • Thank you, it worked for me when i was using a viewpager into a fragment. – O' alone Music May 06 '21 at 19:02
2

I feel kind of stupid. The problem was with the ViewPager as I suspected. After 3h of code debugging I just moved the ViewPager from the layout with the tabs to another layout which basically connects all of the layouts.

Tachanka
  • 53
  • 1
  • 8
1

The below sample code is working fine with viewpager and tabs. Try it out.

  1. Main activity layout

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />
    
    </android.support.design.widget.AppBarLayout>
    
    <android.support.design.widget.TabLayout
        android:id="@+id/tab_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="?attr/actionBarSize" />
    
    <include layout="@layout/content_main" />
    
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_dialog_email" />
    

Then viewpager container layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/content_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="?attr/actionBarSize"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.test.myapplication.MainActivity"
    tools:showIn="@layout/app_bar_main">

    <android.support.v4.view.ViewPager
        android:id="@+id/page_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FF0000" />
</RelativeLayout>

And here is the main activity part:

package com.test.myapplication;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.*;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

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

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        ViewPager pager = (ViewPager)findViewById(R.id.page_container);
        pager.setAdapter(new Adapter(getSupportFragmentManager()));
        TabLayout tabs = (TabLayout)findViewById(R.id.tab_container);
        tabs.setupWithViewPager(pager, true);
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camera) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }


    public static class Adapter extends FragmentStatePagerAdapter {
        private String[] titles = new String[] {"ONE", "TWO"};

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

        @Override
        public Fragment getItem(int position) {
            switch (position){
                case 0:
                    return new com.test.myapplication.Fragment();
                case 1:
                    return new Fragment1();
            }
            return null;
        }

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

        @Override
        public CharSequence getPageTitle(int position) {
            return titles[position];
        }
    }
}
Rahul Shukla
  • 1,150
  • 8
  • 24
0

You are missing setupWithViewPager, and you don't need setOnTabSelectedListener:

tab_layout.setupWithViewPager(viewPager)

Let's look here: http://www.androidhive.info/2015/09/android-material-design-working-with-tabs/

You have to override also getPageTitle in adapter and there return tab title.

Last, don't use <view ..class> in xml, create normal xml view:

 <android.support.v4.view.ViewPager 
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentStart="true"
     android:id="@+id/view_pager"
     android:layout_below="@+id/tab_layout"/>
Tomasz Czura
  • 2,174
  • 10
  • 18
0

try this:

in your layout:

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.design.widget.TabLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_alignParentStart="true"
    android:id="@+id/tab_layout">

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

<android.support.v4.view.ViewPager
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentStart="true"
    android:id="@+id/view_pager"
    android:layout_below="@+id/tab_layout" />

</RelativeLayout>

in activity:

 TabLayout tab_layout = (TabLayout) findViewById(R.id.tab_layout);
    tab_layout.addTab(tab_layout.newTab().setText("CASUAL"));
    tab_layout.addTab(tab_layout.newTab().setText("RANKED"));
    tab_layout.setTabGravity(TabLayout.GRAVITY_FILL);

    final ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
    PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), tab_layout.getTabCount());
    viewPager.setAdapter(adapter);
    viewPager.setOffscreenPageLimit(2);
    tab_layout.post(new Runnable() {
    @Override
    public void run() {
        tab_layout.setupWithViewPager(viewPager);
      }
   });
    tab_layout.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) {

        }
    });

PagerAdapter :

    public class PagerAdapter extends FragmentStatePagerAdapter {
int mNumOfTabs;

// an array of tab titles
    private String tabTitles[] = new String[]{"CASUAL", "RANKED"};

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

@Override
public Fragment getItem(int position) {

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

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

     @Override
    public CharSequence getPageTitle(int position) {
        return tabTitles[position];
    }
}
rafsanahmad007
  • 23,062
  • 6
  • 43
  • 58
0

If you are using any tablayout with viewpager inside NestedScrollView, make sure to put android:fillViewport="true" Reference in the nested scrollview. Note that, if you are working with navigation drawer, your fragment may not have a nested scrollview, but your activity fragment container maybe inside a nested scroll view. Because even an empty layout with a background color (for debugging the issue) does not show up, so it was not the problem of view pager in my case, it was the problem with nested scroll view.

Debugging tip: Instead of viewpager, put some layout and set a background color to see if the layout is visible. If the layout itself is not visible, then you have issue with the parent layout, most probably NestedScrollView.

Reejesh PK
  • 464
  • 1
  • 7
  • 21