I spent the last days searching for a way to communicate two fragments, there are tons of answers and tutorials about how to do it but none of them worked for me. I tried parcelable, boundle, interfaces but nothing worked (probably because I made a mistake implementing them).
The tricky thing is that most tutorials explain a basic case with two fragments with IDs in their layouts but my app has a more complex architecture. Check the image below:
The aim is to send a custom object from the ListView (lv1) to ListView (lv2). Each listview is in a fragment created using FragmentPagerAdapter and belong to a different Drawer Fragment as explained in the image.
Can anyone point me in the right direction here?
MainActivity code of how Navigation Drawer fragments are created:
#Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
String title = getString(R.string.app_name);
HomeFragment homeFragment = null;
QuotesFragment quotesFragment = null;
WatchlistFragment watchlistFragment = null;
switch (position) {
case 0:
homeFragment = new HomeFragment();
title = getString(R.string.title_inicio);
break;
case 1:
quotesFragment = new QuotesFragment();
title = getString(R.string.title_cotizaciones);
break;
case 2:
watchlistFragment = new WatchlistFragment();
title = getString(R.string.title_messages);
break;
}
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
switch (position) {
case 0:
fragmentTransaction.replace(R.id.container_body, homeFragment, "HomeFragment");
break;
case 1:
fragmentTransaction.replace(R.id.container_body, quotesFragment, "QuotesFragment");
break;
case 2:
fragmentTransaction.replace(R.id.container_body, watchlistFragment, "WatchlistFragment");
break;
}
Also, check below the code of how fragmentpageadapter creates the fragmenttabs:
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(new QuotesIndexespage(),getResources().getString(R.string.one));
adapter.addFragment(new QuotesCurrenciesPage(),getResources().getString(R.string.two));
adapter.addFragment(new QuotesCommoditiesPage(),getResources().getString(R.string.three));
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);
}
}
Related
I have an Activity that is using viewpager and fragments with tabs. I pass data from the activity to the Fragments but it is always showing the wrong data for the specific tabs. I have one fragment which is supposed to query data depending on the arguments passed through the bundle.
private Fragment createFragment(String title){
HomeFragment fragment = new HomeFragment();
Bundle bundle = new Bundle();
bundle.putString("category",title);
fragment.setArguments(bundle);
return fragment;
}
Then I pass this function on the viewpager like so:
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(createFragment("Item 1"),"Tab 1");
adapter.addFragment(createFragment("Item 2"),"Tab 2");
adapter.addFragment(createFragment("Item 3"),"Tab 3");
adapter.addFragment(createFragment("Item 4"),"Tab 4");
adapter.addFragment(createFragment("Item 5"),"Tab 5");
Lastly I get the argument passed like so:
String argument = this.getArguments().getString("category");
the problem is when I'm on Tab 1, It returns Item 2. But when I visit all tabs, it starts to return the correct item i.e. Item 1 when on Tab 1.
Where is the problem?
EDIT:
the ViewPagerAdapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragList = new ArrayList<>();
private final List<String> titleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragList.get(position);;
}
public void addFragment(Fragment fragment, String title) {
fragList.add(fragment);
titleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return titleList.get(position);
}
#Override
public int getCount() {
return fragList.size();
}
}
Maybe you could create the adapter class and make sure you're passing the right fragment on the right position. It might be a problem with the adapter adding the fragments on the wrong position the way you are instantiating them.
class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 1: return createFragment("Item 1"),"Tab 1");
case 2: return createFragment("Item 2"),"Tab 2");
case 3: return createFragment("Item 3"),"Tab 3");
case 4: return createFragment("Item 4"),"Tab 4");
case 5: return createFragment("Item 5"),"Tab 5");
}
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
i have a viewPager that contains 3 tabs fragments.
the first and the second fragments works fine but when i sweep to the third tab
i do not see him.
the third tab has shown only when the activity with the viewPager has reload(move to another activity and return).
my code:
private void setupViewPager(ViewPager viewPager) {
adapter = new PagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment1(), Constants.TAB_0);
adapter.addFragment(new Fragment2(), Constants.TAB_1);
adapter.addFragment(new Fragment3(), Constants.TAB_2);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
}
pager adapter:
public class PagerAdapter extends FragmentPagerAdapter {
/*
* Arraylist used to contain the fragments
* and contain fragments title's
*/
private final List<Fragment> fragmentList = new ArrayList<>();
private final List<String> fragmentTitleList = new ArrayList<>();
public PagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return fragmentList.size();
}
//Adds the fragment and it's title. Called in MainActivity
public void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
//Retrieves the title of the tab
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
Here is my adapter, on getItem I set the fragment object to the Fragment activity.
public class SectionPagerAdapter extends FragmentPagerAdapter {
Fragment fragment;
public SectionPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 0){
fragment = new FragmentOne();
}
else if (position == 1){
fragment = new FragmentTwo();
}
else if (position == 2){
fragment = new FragmentThree();
}
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "name one";
case 1:
return "name two";
case 2:
return "name three";
}
return null;
}
}
Then in my main activity I call it like so:
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
SectionPagerAdapter sectionPagerAdapter = new SectionPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(sectionPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
Try replacing your code with above and let me know if it helps!
USE new PagerAdapter(getChildSupportFragmentManager());instead of getSupportFragmentManager()
Try this one !!
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/
I am unable to create dynamic layout for each tabs, i am able to create tabs dynamically by this constructor(public MyPagerAdapter(FragmentManager fm , int noOfTabs)), but coudn't inflate the view for each tabs creating for each fragment which should be dyanmic.
public class MyPagerAdapter extends FragmentPagerAdapter
{
private final String[] TITLES = { "Categories", "Home", "Top Paid", "Top Free", "Top Grossing", "Top New Paid",
"Top New Free", "Trending" };
int noOfTabs;
**public MyPagerAdapter(FragmentManager fm , int noOfTabs)
{
super(fm);
this.noOfTabs = noOfTabs;
}**
/*public MyPagerAdapter(FragmentManager fm)
{
super(fm);
}*/
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return noOfTabs; //TITLES.length;
}
#Override
public Fragment getItem(int position) {
return SuperAwesomeCardFragment.newInstance(position);
}
}
I am facing problem here which should be dynamic and not static as three fragments(FragmentA, FragmentB , FragmentC), it can be any number of fragments depending on the int noOfTabs:
#Override
public Fragment getItem(int position) {
Fragment fragment =null;
switch (position) {
case 0:
fragment = new FragmentA();
break;
case 1:
fragment = new FragmentB();
break;
case 2:
fragment = new FragmentC();
break; }
return fragment;
}
Thanks in advance if any one could help me in this, as i am using this with help of library PagerSlidingTabStrip.
#nbokmans solution may be okay but i've used a container to accomplish that.
Creating a simple host fragment with FrameLayout inside and by replacing fragment was a good dynamic solution for me.
Using Otto EventBus just made it awesome because it can be changed from everywhere with just simple post
#Subscribe
fun changeFragment(type: FragmentTypeEvent){
val ft = activity.supportFragmentManager.beginTransaction()
val frag = getFragment(type)
ft.replace(R.id.container_frame,frag)
ft.commit()
}
I've always worked with FragmentActivity and TabHost to add/remove/replace Fragment programmatically.
What I was using was:
public void addFragments(String tabName, Fragment fragment,
boolean animate, boolean add, Bundle bundle) {
currentSelectedTab = tabName;
if (add) {
hMapTabs.get(tabName).add(fragment);
}
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
if (animate) {
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left);
}
if (bundle!=null){
fragment.setArguments(bundle);
}
ft.replace(R.id.realtabcontent, fragment, tabName);
ft.commitAllowingStateLoss();
}
public void removeFragment() {
Fragment fragment = hMapTabs.get(currentSelectedTab).get(
hMapTabs.get(currentSelectedTab).size() - 2);
hMapTabs.get(currentSelectedTab).remove(
hMapTabs.get(currentSelectedTab).size() - 1);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
ft.replace(R.id.realtabcontent, fragment);
ft.commitAllowingStateLoss();
}
With that, everything works OK.
Now I'm trying to manage this Fragment's behavior on a page of my ViewPager.
I've been searching on StackOverFlow for three hours and I get confused everytime more and more. Tried with public functions on FragmentPagerAdapter for example.
And what only worked makes me a white blank screen on adding Fragments.
How would you do it?
Thanks in advance.
I found a workaround for my problem but I don't know if it's effective.
I'm defining a HashMap to keep my Fragments:
private HashMap<Integer, ArrayList<Fragment>> hMapTabs = new HashMap<Integer, ArrayList<Fragment>>();
then I initializate it and I add my first fragments of every position (in this case, the fragments are the same).
hMapTabs.put(0, new ArrayList<Fragment>());
hMapTabs.put(1, new ArrayList<Fragment>());
hMapTabs.put(2, new ArrayList<Fragment>());
hMapTabs.get(0).add(new PrimerFragment());
hMapTabs.get(1).add(new PrimerFragment());
hMapTabs.get(2).add(new PrimerFragment());
and I set my adapter to my ViewPager. This would be the FragmentAdapterPager:
public class CollectionPagerAdapter extends FragmentStatePagerAdapter {
final int NUM_ITEMS = 3; // number of tabs
FragmentManager fm;
HashMap<Integer, ArrayList<Fragment>> hMapTabs;
public CollectionPagerAdapter(FragmentManager fm, HashMap<Integer, ArrayList<Fragment>> hMapTabs) {
super(fm);
this.fm = fm;
this.hMapTabs = hMapTabs;
}
#Override
public Fragment getItem(int position) {
return hMapTabs.get(position).get(hMapTabs.get(position).size()-1);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public CharSequence getPageTitle(int position) {
String tabLabel = null;
switch (position) {
case 0:
tabLabel = "tab1";
break;
case 1:
tabLabel = "tab2";
break;
case 2:
tabLabel = "tab3";
break;
}
return tabLabel;
}
}
from every fragment, I can add or remove fragments with the functions:
public void addFragment(int position, Fragment frag) {
hMapTabs.get(position).add(frag);
mCollectionPagerAdapter = new CollectionPagerAdapter(
getSupportFragmentManager(), hMapTabs);
mViewPager.setAdapter(mCollectionPagerAdapter);
}
public void removeFragment(int position) {
hMapTabs.get(position).remove(
hMapTabs.get(position).size() - 1);
mCollectionPagerAdapter = new CollectionPagerAdapter(
getSupportFragmentManager(), hMapTabs);
mViewPager.setAdapter(mCollectionPagerAdapter);
}
#Override
public void onBackPressed() {
int position = mViewPager.getCurrentItem();
if (hMapTabs.get(position).size() <= 1) {
super.onBackPressed();
} else {
removeFragment(position);
}
}
but what I can't do is adding an Animation... how would I do it? :D