im using new away to use tabs with viewPager, but i dont know how to know what is the current fragment showing.
At the moment im getting an issue, that is loggint two items on method getItems, from pagerAdapater. I mean, when fragment loads, i see two getItems logs.
So, i dont know what is the fragament shwoing at the moment, and pass that information for my class fragment.
I have two classes
SlidingTabLayout and SlidingTabStrip, in my project.
And my classes...
Note: I didnt post my Fragment class, because is a simple class and doesnt matter for debug, because issue is happening before.
MyActivity
public class MyFragmentActivity extends ActionBarActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(myactivity.xml);
Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
}
ViewPager mViewPager = (ViewPager) this.findViewById(R.id.viewpager);
mViewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
SlidingTabLayout mSlidingTabLayout = (SlidingTabLayout) this
.findViewById(R.id.sliding_tabs);
mSlidingTabLayout.setViewPager(mViewPager);
}
}
MyPagerAdapter
public class MyPagerAdapter extends FragmentPagerAdapter{
private static int TABS = 6;
public MyPagerPagerAdapter(FragmentManager fm) {
super(fm);
}
/**
* Return the Fragment associated with a specified position.
*/
#Override
public Fragment getItem(int position) {
Log.d("Just for log:" + position);
return new MyFragment();
}
/**
* Return the number of views available.
*/
#Override
public int getCount() {
return TABS;
}
#Override
public CharSequence getPageTitle(int position) {
switch(position){
case 0: return "TAB 1";
case 1: return "TAB 2";
case 2: return "TAB 3";
case 3: return "TAB 4";
case 4: return "TAB 5";
case 5: return "TAB 6";
}
return "";
}
}
myactivity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<my.package.common.view.SlidingTabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</my.package.common.view.SlidingTabLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/white" >
</android.support.v4.view.ViewPager>
</LinearLayout>
Every class that extends Fragment can override the following method:
#Override
public void setUserVisibleHint(boolean isVisibleToUser)
so, this gives you (or the fragment) the information that it is now
becoming visible (or unvisible). You can then pass this information
to holder Activity class.
Related
so i have the classic viewpager in a tablayout that looks something like this:
My viewPagerAdapter class looks like this:
public class HomePagerAdapter extends FragmentPagerAdapter {
int mNumOfTabs;
public HomePagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabHomeFragment tab1 = new TabHomeFragment();
return tab1;
case 1:
TabShopFragment tab2 = new TabShopFragment();
return tab2;
case 2:
TabMeFragment tab3 = new TabMeFragment();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
So now on one of the tabs i need to add a fragment on top of it. so its a search fragment really. i do a search in the tab bar and i want the back end search results to appear in only ONE of the tabs (the first one). but i want the search results displayed in a fragment called searchFragmentResults and i want it to be laid out on top of the first tab. Then when user hits the back button it will just go back to the original content in the first tab. Is this possible with view pager ?
so visually when i hit the search icon on the first tabs tabBar it should bring up a searchView and when i search for the users query it should bring up a another fragment with the results but only in the tab that it started from. Here is an example:
i cant call fragtransaction.replace(somecontentview, somefragment); (or its add method) because i did not add them to a contentview. i let the viewpager do it for me. So how is this achieved ?
i figured out how to do this. The tab should be a fragment who's purpose is to only contain other fragments. the idea is based off of this SO. But i had a need to do it for a viewPager. Lets go through the steps. first the viewpager adapter:
public class HomePagerAdapter extends FragmentStatePagerAdapter {
//integer to count number of tabs
int tabCount;
private Fragment mCurrentFragment;
private String[] tabTitles = new String[]{"tab0", "tab1", "tab2", "tab3"};
//Constructor to the class
public HomePagerAdapter(FragmentManager fm, int tabCount) {
super(fm);
this.tabCount = tabCount;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabHomeContainerFragment tab1 = new Tab0ContainerFragment();
return tab1;
case 1:
TabShopFragment tab2 = new Tab1ContainerFragment();
return tab2;
case 2:
TabMeFragment tab3 = new Tab2ContainerFragment();
return tab3;
case 3:
TabBagFragment tab4 = new Tab3ContainerFragment();
return tab4;
default:
return null;
}
}
//Overriden method getCount to get the number of tabs
#Override
public int getCount() {
return tabCount;
}
public Fragment getCurrentFragment() {
return mCurrentFragment;
}
//* this is key to get the current tab to pop the fragments afterwards**/
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
mCurrentFragment = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
Lets go into a container to see how it would look:
add this to your xml for all the containers (along with anything else you want visually but they ALL must have the same id of container_framelayout:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="#+id/container_framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" />
</android.support.design.widget.CoordinatorLayout>
you dont have to put it in a coordinatorLayout i just find it fixes some bugs and works well.
In your fragments base class i copied almost the same code from the SO i mentioned above but slight modification if you want to add tag or not:
public void replaceFragment(Fragment fragment, boolean addToBackStack,String tag) {
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container_framelayout, fragment,tag);
transaction.commit();
getChildFragmentManager().executePendingTransactions();
}
public boolean popFragment() {
Log.e("test", "pop fragment: " + getChildFragmentManager().getBackStackEntryCount());
boolean isPop = false;
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
return isPop;
}
Now lets look at the activities layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white"/>
<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:tabTextColor="#color/black"
app:tabSelectedTextColor="#android:color/darker_gray"
/>
Now i'll show you how to set up the tablayout in the activity hosting the tablayout:
its standard:
public class HomePageActivity implements TabLayout.OnTabSelectedListener {
private final int NUM_OF_TABS = 4;
#BindView(R.id.pager)
public ViewPager viewPager;
public HomePagerAdapter adapter;
#BindView(R.id.tabLayout)
TabLayout tabLayout;
#NonNull
#Override
public HomePagePresenter createPresenter() {
return new HomePagePresenter();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_homepage);
ButterKnife.bind(this);
initView();
}
private void initView() {
for (int i = 0; i < NUM_OF_TABS; i++)
tabLayout.addTab(tabLayout.newTab());
adapter = new HomePagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
//Adding adapter to pager
viewPager.setAdapter(adapter);
tabLayout.addOnTabSelectedListener(this);
tabLayout.setupWithViewPager(viewPager);
// configure tab icons
int[] imageTabResId = {
R.drawable.welcome1,
R.drawable.welcome2,
R.drawable.welcome3,
R.drawable.welcome1};
for (int i = 0; i < imageTabResId.length; i++) {
tabLayout.getTabAt(i).setIcon(imageTabResId[i]);
}
}
/** this is key. we get the current fragment showing and pop it **/
#Override
public void onBackPressed() {
boolean isPopFragment = false;
isPopFragment = ((BaseFragment) adapter.getCurrentFragment()).popFragment();
if (!isPopFragment) {
finish();
}
}
#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) {
}
}
I guess the major part is onBackPress getting the current fragment.
I am sorry on the duplicate question but I didn't get answer for my problem.
I create app with TabActivity and also trying to replace one fragment from fragment itself, I read in https://developer.android.com/training/basics/fragments/fragment-ui.html how to do it and i created interface in my fragment that i want to be replace with another,
I implement the interface in my MainActivity and still when running my app it show me container itself.
here is my code:
Main Activity:
public class MainActivity extends FragmentActivity implements New2.OnReplaceFragment {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
public static MainActivity instance = null;
public static MainActivity getInstance(){
return instance;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.frame_container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.icon_info);
tabLayout.getTabAt(1).setIcon(R.drawable.icon_heart_rate_sensor_jpg);
tabLayout.getTabAt(2).setIcon(R.drawable.icon_graph_jpg);
instance = this;
}
#Override
public void onReplaceFragment(Class fragmentClass) {
Fragment fragment = null;
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
// Insert the fragment by replacing any existing fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container,fragment);
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
switch (position) {
case 0:
// New1 tab1 = new New1();
return New1.newInstance();
case 1:
return New2.newInstance();
case 2:
return New3.newInstance();
default:
return null;
}
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "SECTION 1";
case 1:
return "SECTION 2";
case 2:
return "SECTION 3";
}
return null;
}
}
}
my fragment that I want to replace
Fragment:
public class New2 extends Fragment {
TextView name;
Button change;
ImageView image1;
Animation anime;
private OnReplaceFragment dataPasser;
public static New2 newInstance(){
New2 fragment = new New2();
return fragment;
}
public New2(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_new2, container, false);
name = (TextView) rootView.findViewById(R.id.nameTt);
change = (Button) rootView.findViewById(R.id.changeBtn);
image1 = (ImageView) rootView.findViewById(R.id.image1);
anime = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),R.anim.zoom);
change.setOnClickListener(changeName);
return rootView;
}
View.OnClickListener changeName = new View.OnClickListener() {
#Override
public void onClick(View view) {
image1.startAnimation(anime);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run(){
dataPasser.onReplaceFragment(Result.class);
}
},1000);
}
};
public interface OnReplaceFragment {
public void onReplaceFragment(Class fragmentClass);
}
#Override
public void onAttach(Activity a) {
super.onAttach(a);
try {
dataPasser = (OnReplaceFragment) a;
} catch (ClassCastException e) {
throw new ClassCastException(a.toString() + " must implement onDataPass");
}
}
}
the fragment that i want to display
public class Result extends Fragment {
TextView textView;
Button btnBack;
public static Result instance = null;
public static Result getInstance(){
return instance;
}
public Result() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_result, container, false);
textView = (TextView) v.findViewById(R.id.text11);
btnBack = (Button) v.findViewById(R.id.btnBack);
textView.setText("working!!");
Toast.makeText(getActivity().getApplicationContext(),"working",Toast.LENGTH_LONG).show();
return v;
}
}
Main Activity 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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.example.hercules.tadhosttutrial.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/appbar_padding_top"
android:background="#color/red"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
New2 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.example.hercules.tadhosttutrial.New2"
android:background="#color/yellow">
<!-- TODO: Update blank fragment layout -->
<Button
android:id="#+id/changeBtn"
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
android:text="change"/>
<ImageView
android:id="#+id/image1"
android:background="#drawable/icon_complete"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/>
Result 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"
android:background="#color/colorAccent"
tools:context="com.example.hercules.tadhosttutrial.Result">
<!-- TODO: Update blank fragment layout -->
<Button
android:id="#+id/btnBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="back"/>
<TextView
android:id="#+id/text11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="WORKING"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:textSize="70dp"
/>
</RelativeLayout>
What i mean, is making MainActivity as a main container for all fragments, either with tabs or just a regular fragment,
1- Main Activity XML: remove ViewPager, add a FrameLayout instead (use same id)
2- Create new fragment TabsFragment with this 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.example.hercules.tadhosttutrial.New2"
android:background="#color/yellow">
<android.support.v4.view.ViewPager
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</RelativeLayout>
3- Move initializing SectionsPagerAdapter and ViewPager from main activity to TabsFragment:
this part:
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
and this:
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.frame_container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.icon_info);
tabLayout.getTabAt(1).setIcon(R.drawable.icon_heart_rate_sensor_jpg);
tabLayout.getTabAt(2).setIcon(R.drawable.icon_graph_jpg);
4- I think moving SectionsPagerAdapter class in a new file is better too.
now if you want default view for app to be the tabs, then in MainActivity at onCreate() show TabsFragment by calling your method:
onReplaceFragment(TabsFragment.class);
now every thing should work fine, because the idea here is to replace the fragment displayed in main activity with another one
in this case TabsFragment, Result, and New2
not to replace viewpager fragments (because as i told you this is managed via the adapter) not by calling replace()
you may need to play around this, it's not a final code, just something to give you idea about it.
I have a project that uses Action Bar Tabs(with ViewPager).
Tabs move really smoothly when swiping between them, but I need to add two sub tabs, in TAB 2, then move to the next tabs or of course back, just like on the Glassdoor or Flipboard.
Please help.
MainActivity
public class MainActivity extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return Tab1Fragment.newInstance();
case 1:
return Tab2Fragment.newInstance();
default:
return Tab3Fragment.newInstance();
}
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Tab 1";
case 1:
return "Tab 2";
case 2:
return "Tab 3";
}
return null;
}
}
}
activity_main.xml
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/appbar_padding_top"
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:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
Tab2Fragment- where i want to nest SubTab1Fragment and SubTab2Fragment
public class Tab2Fragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
public Tab2Fragment() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
public static Tab2Fragment newInstance() {
Tab2Fragment fragment = new Tab2Fragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_tab2, container, false);
}
}
fragment_tab2.xml
<FrameLayout 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.r3dm4n.testprojectapp.Tab2Fragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment" />
I figured this out.
I've also posted a demo project on Github
In the MainActivity you need to return a new Fragment for the one you want "nested" like this:
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return Tab1Fragment.newInstance();
case 1:
return new Tab2Fragment();
default:
return Tab3Fragment.newInstance();
}
In TAB2 fragment, where you want the other nested fragments make the following changes:
public class Tab2Fragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_tab2, container, false);
ViewPager mViewPager = (ViewPager) view.findViewById(R.id.container_main);
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
return view;
}
private class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return Nest1Fragment.newInstance(1);
default:
return Nest2Fragment.newInstance(2);
}
}
#Override
public int getCount() {
// Show 4 total pages.
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Nested 1";
default:
return "Nested 2";
}
}
}
}
fragment_tab2.xml
<android.support.v4.view.ViewPager
android:id="#+id/container_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:layout_scrollFlags="scroll|enterAlways">
<android.support.design.widget.TabLayout
android:id="#+id/tabs2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
</android.support.v4.view.ViewPager>
Take a look at this answer
It might help
ViewPager nested in ViewPager
Also while adding sub tabs You can add a condition like this in the listener for moving to next tab
if(mPager.getCurrentItem() >=2)
mParentPager.setCurrentItem()=mParentPager.getCurrenItem()+1
This for moving to previous tab
if(mPager.getCurrentItem() ==0)
mParentPager.setCurrentItem()=mParentPager.getCurrenItem()-1
I have total of 5 fragments inside a Viewpager and I want to display 2 tabs on either side of the current visible tab.
Example : My current tab is 2 . And I want tab 0, tab 1 to left and tab 3,tab 4 to the right to be displayed at once.
I tried setting viewPager.setOffscreenPageLimit(2) but it didnt' work. I still see only 1 tab displayed on either sides. What am I missing?
public class TabsFragment extends Fragment {
mViewPager = (ViewPager) view.findViewById(R.id.pager);
titleStrip = (PagerTitleStrip) view.findViewById(R.id.titlestrip);
adapter = new TabsPagerAdapter(getChildFragmentManager(), getActivity());
mViewPager.setAdapter(adapter);
mViewPager.setOffscreenPageLimit(2);
mViewPager.setCurrentItem(2);
}
public class TabsPagerAdapter extends FragmentStatePagerAdapter {
private Context context;
public TabsPagerAdapter(FragmentManager fm, Context c) {
super(fm);
context = c;
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstFrag();
case 1:
return new SecondFrag();
case 2:
return new ThirdFrag();
case 3:
return new FourthFrag();
case 4:
return new FifthFrag();
default:
return new SecondFrag();
}
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 5;
}
}
Solved this issue by using TabLayout. Posting the code for future readers.
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Light">
<android.support.v7.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/awesome_toolbar"
android:layout_width="match_parent"
android:layout_height="74dp"
android:background="#ff31353f"
android:paddingTop="20dp"
app:popupTheme="#style/AppTheme"
app:theme="#style/ToolbarTheme"/>
<android.support.design.widget.TabLayout
android:id="#+id/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/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
public class TabsFragment extends Fragment {
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mViewPager = (ViewPager) view.findViewById(R.id.pager);
tabLayout = (TabLayout)view.findViewById(R.id.tabs);
adapter = new TabsPagerAdapter(getChildFragmentManager(), getActivity());
adapter.addFragment(new FirstFrag(), getResources().getString(R.string.frag1));
adapter.addFragment(new SecondFrag(), getResources().getString(R.string.frag2));
adapter.addFragment(new ThirdFrag(), getResources().getString(R.string.frag3));
adapter.addFragment(new FourthFrag(), getResources().getString(R.string.frag4));
adapter.addFragment(new FifthFrag(), getResources().getString(R.string.frag5));
mViewPager.setAdapter(adapter);
mViewPager.setOffscreenPageLimit(2);
mViewPager.setCurrentItem(2);
tabLayout.setupWithViewPager(mViewPager);
}
You need to modify your ViewPager adapter. Override the public Fragment getItem(int position) method, and create a custom Fragment that will contain the current fragment and the fragment in position-1 in the left, position+1 in the right. You may have to override the public int getCount() method too. I didn't try an implementation like this before but I think this is the way to approach this.
I have a MainActivity which contains a Sliding drawer for menu and a FragmentContainer to switch fragments.
I have a Fragment called History which has a layout like this
<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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<com.astuetz.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#color/colorPrimary"
android:textColor="#FFFFFF"
app:pstsIndicatorColor="#FFFFFF" />
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/tabs" />
</RelativeLayout>
And the class looks like this
public class HistoryFragment extends Fragment {
public HistoryFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_history, container, false);
// Initialize the ViewPager and set an adapter
ViewPager pager = (ViewPager) view.findViewById(R.id.pager);
pager.setAdapter(new PagerAdapter(getActivity().getSupportFragmentManager()));
// Bind the tabs to the ViewPager
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) view.findViewById(R.id.tabs);
tabs.setViewPager(pager);
return view;
}
class PagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = {"Last Transaction", "History"};
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new LastTransaction();
case 1:
return new AboutFragment();
}
return null;
}
}
}
This History page works fine the first time when it is called from the NavigationSlider menu. The history page contains two sliding tabs with two fragments. These are displayed the first time and everything works fine.
The problem happens, when they are called the second time or after that.
There is no error shown, the layout is loaded, the sliding tabs are shown, but their fragments are not shown and the sliders malfunction.
What may be the reason for this problem ?
I tried to use a different approach for implementing the sliders in fragments as per this StackOverflow answer. Still the same problem.
Thanks in advance.
replace
pager.setAdapter(new PagerAdapter(getActivity().getSupportFragmentManager()));
with
pager.setAdapter(new PagerAdapter(getActivity().getChildFragmentmanager()));
Reason:
The CHILD FragmentManager is the one that handles Fragments contained within the Fragment that it was added to.