add/remove fragment in viewpager using FragmentPagerAdapter - android

I'm using FragmentPagerAdapter to load 4 fragments initially. Now i have another fragment which i want to show only when a click is performed (let say from a button inside other fragments) , and every time that fragment is bring to front, new data of should be in it. So now what should be my logic to do this?
My FragmentPagerAdapater
public class SmallViewPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> allFragments;
public SmallViewPagerAdapter(FragmentManager fm,
ArrayList<Fragment> allFragments) {
super(fm);
this.allFragments = allFragments;
}
#Override
public Fragment getItem(int position) {
return allFragments.get(position);
}
#Override
public int getCount() {
return allFragments.size();
} }
Defining my adapter and adding it to viewpager
private ArrayList<Fragment> frags = new ArrayList<Fragment>();
private SmallViewPagerAdapter vpAdapter;
viewPager.setPagingEnabled(false);
viewPager.setOffscreenPageLimit(3);
frags.add(new MapContainerFragment(this));
frags.add(new FavoriteContainerFragment(this));
frags.add(new AllOffersFragment(this));
frags.add(new RegisterFragment(this));
vpAdapter = new SmallViewPagerAdapter(getSupportFragmentManager(),
frags);
viewPager.setAdapter(vpAdapter);
Now for some reason i have to put setOffscreenPageLimit(3) because i dont want my other fragments to reload when ever they brought back.
Thanks.

you should change this method
#Override
public int getCount() {
return numberOfFragmentsToShow;
}
numberOfFragmentsToShow is an int variable you change when you want to show more/less fragments
keep a reference to an instance of SmallViewPagerAdapter and when you are chaining the number of fragments, make sure you call smallViewPagerAdapterInstance.notifyDataSetChanged(); for the changes to take effect.
Alternately you could be adding/removing items from the arraylist of fragments, but you must call smallViewPagerAdapterInstance.notifyDataSetChanged(); to see the changes.

Well the solution i have found for this is to add my 5 fragments on initialization of viewpager
private ArrayList<Fragment> frags = new ArrayList<Fragment>();
private SmallViewPagerAdapter vpAdapter;
viewPager.setPagingEnabled(false);
viewPager.setOffscreenPageLimit(4);
frags.add(new MapContainerFragment(this));
frags.add(new FavoriteContainerFragment(this));
frags.add(new AllOffersFragment(this));
frags.add(new RegisterFragment(this));
frags.add(new DetailFragment(this));
vpAdapter = new SmallViewPagerAdapter(getSupportFragmentManager(),
frags);
viewPager.setAdapter(vpAdapter);
and created a static function for updating the view on every click
public static void updateView(Context context, String offerId) {
offer = new DBHandler(context).getOffersById(offerId);
if (offer != null) {
offerName.setText(offer.getTitle());
offerSave.setText(offer.getListTitle());
ImageLoader.getInstance().displayImage(
Constants.URLHelper.getUrlForOfferImage(offer.getId(),
offer.getLogoId()), offerImage);
detailText.setText(Html.fromHtml(offer.getDetailDesc().replace(
"COLOR=\"#0B333C\"", " ")));
} else {
Toast.makeText(context, "No Offer detail found!!",
Toast.LENGTH_LONG).show();
}
}
and on the button click i just change the current selected page of the viewpager.
NOTE: I know its a bad approach but that's all I can come up for the solution to my problem. If someone have a better idea or thinks that this approach isn't better, please tell me.

Add or remove fragment in viewpager dynamically:
Call setupViewPager(viewPager) on activity start.
To load a different fragment, call setupViewPagerCustom(viewPager):
private void setupViewPager(ViewPager viewPager)
{
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new fragmnet1(), "HOME");
adapter.addFrag(new fragmnet2(), "SERVICES");
viewPager.setAdapter(adapter);
}
private void setupViewPagerCustom(ViewPager viewPager)
{
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new fragmnet3(), "Contact us");
adapter.addFrag(new fragmnet4(), "ABOUT US");
viewPager.setAdapter(adapter);
}
//Viewpageradapter, handles the views
static class ViewPagerAdapter extends FragmentStatePagerAdapter
{
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager){
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
#Override
public int getItemPosition(Object object){
return PagerAdapter.POSITION_NONE;
}
public void addFrag(Fragment fragment, String title){
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position){
return mFragmentTitleList.get(position);
}
}

Related

Refresh and load one particular fragment of the previous activity

I have 3 fragments in a activity. One of the fragment displays the list of items along with price and quantity. On selecting any of the item , a new activity will start that will display the details of the item. In this activity we can change the item price , quantity etc.
I want to reload and display the fragment(with updated values) in previous activity just after saving the changes in the item detail activity.
Here is the code for first activity:
public class SupplierHomeActivity extends AppCompatActivity implements
ActionBar.TabListener {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_supplier_home);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
// getSupportFragmentManager().addOnBackStackChangedListener(getListener());
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment(), "PROFILE");
adapter.addFragment(new InventoryFragment(), "INVENTORY");
adapter.addFragment(new SupplierOrderFragment(), "ORDERS");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(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);
}
}
}
Thank you in advance.
You need to declare your adapter globally and add onResume() method to notify your adapter that data has been changed for the content.

ViewPager Not Synched with TabLayout

I have a ViewPager and Tablayout that shows nth number of items. The Tabs are populated with the correct page titles and the ViewPager contained Fragments display the correct fine except that the selected Tab is not synched with the ViewPager current item.
The selected Tab position is 1 less than the position of viewpager current item. Here is the Viewpager adapter.
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm){
super(fm);
}
#Override
public Fragment getItem(int position) {
Recipe selectedRecipe = getRecipeList().get(position);
return RecipeDetailFragment.newInstance(selectedRecipe.getId);
}
#Override
public int getCount() {
return .getRecipeList().size();
}
#Override
public CharSequence getPageTitle(int position) {
Recipe selectedRecipe = .getRecipeList().get(position);
String title = selectedRecipe.getTitle();
return title ;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
Here is how I setup the ViewPager
private void setupViewPager() {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
}
Here is what the output looks like
Edit 1:
I think the problem have to do with how the getItem method of the ViewPager is being called, here is log of left and right scroll for10 items
instead of using static variable in fragment you can use,
public function in fragment like below.
add
#Override
public Fragment getItem(int position) {
Recipe selectedRecipe = getRecipeList().get(position);
RecipeDetailFragment receiptFRagment= new ReceiptFragment();
receiptFragment.setData(selectedRecipe.getId);
return receiptFragment;
}
instead of this
#Override
public Fragment getItem(int position) {
Recipe selectedRecipe = getRecipeList().get(position);
return RecipeDetailFragment.newInstance(selectedRecipe.getId);
}
Add public function in fragment,
public void setData(int id){
this.id= id;
}
Finally, this is how I synched the ViewPager selected item with the Tablayout selected tab.
void selectPage(final int pageIndex){
new Handler().postDelayed(
new Runnable() {
#Override public void run() {
tabLayout.setSmoothScrollingEnabled(true);
tabLayout.setScrollPosition(pageIndex, 0f, true);
}
}, 100);
}
Then I called this method from two places, first when I setup Viewpager
recipePosition = getIntent().getIntExtra(Constants.RECIPE_POSITION, 0);
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
if (recipePosition > 0){
recipePosition--;
}
viewPager.setCurrentItem(recipePosition,true);
selectPage(recipePosition);
And then second in the setItem
Recipe selectedRecipe = getRecipeList().get(position);
RecipeDetailFragment receiptFRagment= new ReceiptFragment();
receiptFragment.setData(selectedRecipe.getId);
selectPage(position);
return receiptFragment;
Its works, I still could not understand why these are not synched by default!

opening a layout (xml) inside a fragment instead of string text input

Problem: I was modifying a small app where three tabs are there in fragment but all refers to text string. I wanted to use layout xml so that I can make good graphics in it. How can I do it in this code:
Information_tab refers to a string where I can put text, but I want a layout.
public class AdapterInformation extends FragmentPagerAdapter {
public AdapterInformation(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
Bundle bundle = new Bundle();
int imgResId = 0;
int tab = 0;
int colorResId = 0;
switch (index) {
case 0:
tab = R.string.information_tab1;
break;
case 1:
tab = R.string.information_tab2;
break;
case 2:
tab = R.string.information_tab3;
break;
}
bundle.putInt("image", imgResId);
bundle.putInt("tab",tab);
bundle.putInt("color", colorResId);
SwipeTabFragment swipeTabFragment = new SwipeTabFragment();
swipeTabFragment.setArguments(bundle);
return swipeTabFragment;
}
#Override
public int getCount() {
return 3;
}}
you can add fragment layout like this.
private void setupViewPager(final ViewPager viewPager) {
final ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new OneFragment(), "Pending Upload");
adapter.addFragment(new TwoFragment(), "Complete Upload");
viewPager.setAdapter(adapter);
}
and your fragmentPagerAdapter code is like this:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager)
{
super(manager);
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#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);
}
}
and also add your setupViewPager method in onCreate()
viewPager = (ViewPager) findViewById(R.id.viewpager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
setupViewPager(viewPager)
tabLayout.setupWithViewPager(viewPager);
Note: Do not use getItemPosition() method if its possible.. it
will produce redundancy of your listItems or ArrayList.. bcz every
time you swipe to other layout it will refresh page automatically..
its good if want this facility.. but you have write some code
regarding to handle this method.. and its also going to slow your
swipe animation if you have large amount of data.
For more information about tab layout and fragment: you can refer this one:
http://www.androidhive.info/2015/09/android-material-design-working-with-tabs/

Retrieving a dynamically created fragment

My code dynamically creates fragments in a tabbed view, I would like to access one of the fragments when the OnCreate activity is called.
I know that there are 2 methods of retrieving an existing fragment, one by ID and one by Tag.
How is it possible to mark the fragments when they are created to be retrieved later?
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
if(extras !=null) {
// ***Get Fragment Here***
}
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new TabFragment1(), "ONE");
adapter.addFragment(new TabFragment2(), "TWO");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(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);
}
}
The FragmentPagerAdapter already caches the Fragments for you. Each fragment is assigned a tag, and then the FragmentPagerAdapter tries to call
findFragmentByTag
It only calls getItem if the result from findFragmentByTag is null. So you shouldn't have to cache the fragments yourself.
Also, you can get reference of your Fragment in FragmentPagerAdapter using findFragmentByTag() method. The name of the tag is generated this way:
private static String makeFragmentName(int viewId, int index)
{
return "android:switcher:" + viewId + ":" + index;
}
where viewId is the id of ViewPager
AmanSinghal's answer will work, I have an alternative approach. You can create an adapter with a method which returns the currently displayed fragment.
I implemented it here a few years ago: PublicisedFragmentPagerAdapter
Look at the getCurrentPrimaryItem() method

Android add fragment and tab after load?

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.

Categories

Resources