I followed these guidelines to create a Sliding tab layout with fragments. The problem is that I want to dynamically add a tab to the SlidingTabLayout. The following code creates a fragment but it isn't displayed. How can i attach it to the SlidingTabLayout?
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
tableFragment = (ReportTableFragment) adapter.getItem(1);
fragmentTransaction.replace(R.id.pager, tableFragment, tableFragment.getClass().getName());
fragmentTransaction.commit();
This is my ViewPagerAdapter class
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
// Build a Constructor and assign the passed Values to appropriate values in the class
public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb) {
super(fm);
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if(position == 0) // if the position is 0 we are returning the First tab
{
//ReportMapFragment reportMapTab = new ReportMapFragment();
//return reportMapTab;
SupportMapFragment mapTab = new SupportMapFragment();
return mapTab;
}
else
{
return ReportTableFragment.newInstance(1);
}
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return NumbOfTabs;
}
}
The solution is pretty easy :)
You should add this methods to your 'ViewPagerAdapter' and change the CharSequence by this
List<String> titles = new ArrayList<String>();
Now the constructor should be:
public ViewPagerAdapter(FragmentManager fm, List<String> mTitles, int mNumbOfTabsumb) {
super(fm);
this.titles = mTitles;
this.numbOfTabs = mNumbOfTabsumb;
}
Methods to add to the 'ViewPagerAdapter':
public void addTab (String title) {
this.titles.add(title);
this.numbOfTabs++;
this.notifyDataSetChanged();
}
public void deleteTab (int position) {
this.titles.remove(position);
this.numbOfTabs--;
this.notifyDataSetChanged();
}
And from your activity or wherever you call the SlidingTabLayout:
this.mAdapter.addTab("NewTab"); // add a new tab
this.mAdapter.deleteTab(0); // or delete a current tab
this.mTabs.setViewPager(this.mPager); // don't forget this line, is the key
Pay attention to the 'getItem' method in your 'ViewPagerAdapter' cause now you are adding tabs dynamically ;)
I.
Related
enter image description here for (int i = 0; i < mFragmentTitleList.size(); i++) {
mFragmentList.add(new MenuListFragment());
}
Problem is when i select or swipe tab it will display products of previous tab.
suppose i have 5 tabs when i click or select 4th tab it will call 3rd tab or 2nd tab's products.
class ViewPagerAdapter extends FragmentPagerAdapter {
private List<android.support.v4.app.Fragment> mFragmentList = new ArrayList<>();
private List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm, List<android.support.v4.app.Fragment> fragments, List<String> titleLists) {
super(fm);
this.mFragmentList = fragments;
this.mFragmentTitleList = titleLists;
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList == null ? 0 : mFragmentList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
public void onTabSelected(TabLayout.Tab tab) {
menutitle = tab.getText().toString();}
in my api call i pass this title
if(child_menu_arrayJSONObject.getString("name").equals(CommonDetailFragment.menutitle))
You need to pass a title from FragmentPagerAdapter to MenuListFragment() based on the title then you can load the relevant data into the listview. you can refer this link on how to pass variable from FragmentPagerAdapter to Fragment.
Edit: i have added a sample application please check this link
I have viewpager that has 4 fragments.
I have set the offscreenPageLimit to 4 and did not override getItemPosition of the adapter because I don't want them to be re-created every time when I change tabs.
Now, there will be a scenario when I want a particular fragment to be re-created (it means to call onCreateView).
That is before I select or when I select that fragment again.
How to do this?
Please try this adapter. This recover to re-create fragment again.
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private Fragment[] fragments;
private String[] titleList;
private int index;
public ViewPagerAdapter(FragmentManager fm, String[] titleList){ // titleList is list of title of fragments
super(fm);
fragments = new Fragment[titleList.length];
this.titleList = titleList;
}
#Override
public Fragment getItem(int position) {
Fragment fragment;
if (fragments[position] == null){
YourFragment yourFragment = new YourFragment();
fragment = yourFragment;
fragments[position] = fragment;
return fragment;
}else{
return fragments[position];
}
}
#Override
public int getCount() {
return titleList.length;
}
#Override
public CharSequence getPageTitle(int position) {
return titleList[position].toUpperCase();
}
}
I have a FragmentActivity with two Fragments in it and a sliding tab layout:
String titles[] = new String[] {"Tab One", "Tab Two"};
int numTabs = titles.length;
EventAdapter adapter = new EventAdapter(getSupportFragmentManager(), titles, numTabs);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
SlidingTabLayout sliding_tabs = (SlidingTabLayout) findViewById(R.id.sliding_tabs);
sliding_tabs.setDistributeEvenly(true);
sliding_tabs.setViewPager(pager);
With the FragmentPagerAdapter:
private class EventAdapter extends FragmentPagerAdapter {
private List<String> titles;
private int numTabs;
public void addTab (String title) {
this.titles.add(title);
this.numTabs++;
this.notifyDataSetChanged();
}
public EventAdapter(FragmentManager fm, List<String> mTitles, int mNumTabs) {
super(fm);
this.titles = mTitles;
this.numTabs = mNumTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 2:
return new FragThree();
case 1:
return new FragTwo();
default:
return new FragOne();
}
}
#Override
public String getPageTitle(int position) {
return titles.get(position);
}
#Override
public int getCount() {
return numTabs;
}
}
Some time down the line, I would like to dynamically add the third tab to this layout. Is there a way to do this in code? As you can see, I already have the PagerAdapter set up to catch the third tab. I just need to load it in...
You need to add this method to your adapter EventAdapter :
public void addTab (String title) {
this.titles.add(title);
// this is the variable returned from getCount method
this.numbTabs++;
this.notifyDataSetChanged();
}
Main purpose is to add the tab and call notifydatasetchanged.
Now call addTab on this adapter's object and tab will be added.
after addTab do sliding_tab.setViewPager(this.pager);
Please accept if this solves the purpose.
In my project I have a tab layout and a fragments viewpager. When I load the fragments and tabs the tab index and the displayed fragment is out of sync, and also when I swipe back and forth the fragments are not in sync with the tabs. I checked the getItem(int position) and the getTitle(int position) methods both have the same position number and the corresponding entries in the ArrayList<Fragments> and the ArrayList<String> (for tab headings) are correct but some how the tabs display is out of sync with the view pager.
Here is my fragmentPagerAdapter.java
public class DetailsFragmentPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragments;
private ArrayList<String> titles;
public DetailsFragmentPagerAdapter(FragmentManager fm) {
super(fm);
fragments = new ArrayList<>();
titles = new ArrayList<>();
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return titles.size();
}
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
public void setFragment(Fragment fragment, String title) {
fragments.add(fragment);
titles.add(title);
notifyDataSetChanged();
}
}
this is activity on create.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
tabLayout = (TabLayout) findViewById(R.id.detailsTabs);
viewPager = (ViewPager) findViewById(R.id.viewPager);
new GetCategoriesAsync2().execute();
}
the async task's doInBackground is calling is preparing arraylist
and the onPostExecute
#Override
protected void onPostExecute(Void aVoid) {
int size = lists.size();
ArrayList<Fragment> fragments = new ArrayList<>(size);
ArrayList<String> titles = new ArrayList<>(size);
for (int i = 0; i < lists.size(); i++) {
ArrayList<String> x = lists.get(i);
titles.add(x.remove(0));
fragments.add(DetailsListFragment.newInstance(x));
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentPagerAdapter = new DetailsFragmentPagerAdapter(fragmentManager);
fragmentPagerAdapter.setFragments(fragments,titles);
viewPager.setAdapter(fragmentPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
progressDialog.dismiss();
}
I am using design support library 23.0.1 and the build target is 23.
how can I fix this tab layout out of sync?
if you use a TabLayout, you need to connect it to the adapter
If you're using a ViewPager together with this layout, you can use
setTabsFromPagerAdapter(PagerAdapter) which will populate the tabs
using the given PagerAdapter's page titles. You should also use a
TabLayout.TabLayoutOnPageChangeListener to forward the scroll and
selection changes to this layout like so:
ViewPager viewPager = ...;
TabLayout tabLayout = ...;
viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(tabLayout));
Try this, it worked for me
public class DetailsFragmentPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragments= new ArrayList<Fragment>();
private final List<String> titles= new ArrayList<String>();
public DetailsFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
public void setFragment(Fragment fragment, String title) {
fragments.add(fragment);
titles.add(title);
}
}
And Change
fragmentPagerAdapter.setFragments(fragments,titles); To
for (int i=0;i<fragments.size();i++)
{
adapter.setFragments(fragments.get(i),titles.get(i));
}
Check this out
it's a demo app that uses a TabLayout with a ViewPager
https://github.com/chrisbanes/cheesesquare
and if you don't know the number of the fragments that you will have in the ViewPager
your pageadapter should extends FragmentStatePagerAdapter
https://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html
I have an activity that extends FragmentActivity, I use a custom FragmentStatePagerAdapter that extends FragmentStatePagerAdapter, a SlidingTabLayout and a pagerView.
In some cases I want my fragmentActivity to start on a specific (third, if it matters..) tab.
I've tried lots of suggestion I found on SO but non worked. When I tries to use "pager.setCurrentItem(3)" the problem was that onCreateView for that fragment was never called and therefore all objects and values are not assigned properly.
thanks for the help!
EDIT: Adding more info
this is how I init my adapter:
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, NewsTab.class.getName()));
fragments.add(Fragment.instantiate(this, PhotosTab.class.getName()));
fragments.add(Fragment.instantiate(this, AboutTab.class.getName()));
fragments.add(Fragment.instantiate(this, NextTab.class.getName()));
adapter = new ProtestViewPagerAdapter(getSupportFragmentManager(),Titles, NumOfTabs, fragments);
this is my view pager adapter:
public class ProtestViewPagerAdapter extends FragmentStatePagerAdapter {
public final String TAG = "PRTST_V_PGR_ADPTR";
private CharSequence Titles[];
private int NumbOfTabs;
private List<Fragment> fragments;
// Build a Constructor and assign the passed Values to appropriate values in the class
public ProtestViewPagerAdapter(FragmentManager fm, CharSequence mTitles[], int mNumbOfTabs,
List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabs;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
return fragments.get(position);
// switch (position){
// case 0:
// NewsTab news = new NewsTab();
// return news;
// case 1:
// PhotosTab photos = new PhotosTab();
// return photos;
// case 2:
// AboutTab about = new AboutTab();
// return about;
// case 3:
// NextTab next = new NextTab();
// return next;
// default:
// return null;
// }
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return this.Titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return this.NumbOfTabs;
}
}
each of the tabs implements FragmentInterface that only have
void fragmentBecameVisible();
and the "tabs" also extends "MyBaseTab" that extends android.support.v4.app.Fragment