0

I have an Activity with a TabLayout containing 2 Tabs, each with their own Fragment. There is a Fab Button that's in my Activity. When I'm in Tab 1 and I click it, I would like to somehow indicate to the ViewPagerAdapter's getItem() method that "hey, the Button has been clicked. Replace existing Fragment in Tab 1 with another Fragment."

I'm not sure how to do this. I was thinking maybe adding a listener but again do not know how to implement it. Any help would be appreciated.

Main Activity:

public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private ArrayList<Fragment> fragments = new ArrayList<>();
private ArrayList<String> titles = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    CollapsingToolbarLayout collapsingToolbarLayout = (CollapsingToolbarLayout)findViewById(R.id.collapsing_toolbar);
    setSupportActionBar(toolbar);

    fragments.addAll(Arrays.asList(new Tasks(),new Calendar(),new Contacts()));
    titles.addAll(Arrays.asList(getResources().getString(R.string.fragment_task_title),
            getResources().getString(R.string.fragment_cal_title),getResources().getString(R.string.fragment_contacts_title)));
    TabLayout tabLayout = (TabLayout)findViewById(R.id.tabs);

    final FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab);
    fab.hide();

    viewPager = (ViewPager)findViewById(R.id.container);
    ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),fragments,titles);
    viewPager.setAdapter(viewPagerAdapter);
    viewPager.setCurrentItem(1);
    viewPager.addOnPageChangeListener(new 
    tabLayout.setupWithViewPager(viewPager);

    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            fabAction();
        }
    });

    if (savedInstanceState==null){
        if (getSupportActionBar()!=null){
            getSupportActionBar().setDisplayShowTitleEnabled(true);
        }
    }
}
public void fabAction(){
    int current = viewPager.getCurrentItem();

    switch (current){
        case 0:{
            //TELL THE VIEWPAGER ADAPTER THAT BUTTON IS CLICKED AND SWITCH FRAGMENTS
            break;
        }
        case 1:{
            Toast.makeText(this, "IN TAB 2", Toast.LENGTH_LONG).show();
            break;
        }
    }
}}

ViewPagerAdapter:

public class ViewPagerAdapter extends FragmentPagerAdapter{
ArrayList<Fragment> fragments;
ArrayList<String> titles;
private Fragment mFragmentAtPos0;
private FragmentManager fragManager;

//NEED TO IMPLEMENT THE LISTENER IN THIS CLASS TELLING ME THAT THE BUTTON WAS CLICKED IN MAIN ACTIVITY
public ViewPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments, ArrayList<String>titles) {
    super(fm);
    this.fragments = fragments;
    this.titles = titles;
    fragManager = fm;

}

@Override
public Fragment getItem(int position) {
    //Somehow get Indication Here that the button was clicked

    if (position == 0)
    {
        if(mFragmentAtPos0==null){
            mFragmentAtPos0 = new Tasks();
            fragManager.beginTransaction().replace(R.id.container,mFragmentAtPos0).commit();
            notifyDataSetChanged();
        }
        return mFragmentAtPos0;
    }else{
        return fragments.get(position);

    }

}

@Override
public int getCount() {
    return fragments.size();
}

@Override
public CharSequence getPageTitle(int position) {

    return titles.get(position);
}

@Override
public int getItemPosition(Object object)
{
    if (object instanceof Tasks && mFragmentAtPos0 instanceof AddContact)
        return POSITION_NONE;
    return POSITION_UNCHANGED;
}}

This is what I'm trying have occur and got my idea from @wize's answer to a similar issue. There's too many missing pieces in the answer for me to grasp the entirety of the solution: Replace Fragment Inside ViewPager

Community
  • 1
  • 1
Mark F
  • 1,523
  • 3
  • 23
  • 41

1 Answers1

1

This is indeed a bit tricky to do. Maybe you should consider moving your fab to the fragment you want to be changed, and handle the changes inside the fragment. If fab has to be in Activity, you can achieve adding/removing fragments from Pager Adapter itself.

Adapter should look something like this:

    public class CodebaseFragmentPagerAdapter extends FragmentStatePagerAdapter {

    private List<Fragment> mFragmentList = new ArrayList<Fragment>();

    public CodebaseFragmentPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    public void removeItem(int position){
        mFragmentList.remove(position == 0 ? 0 : position - 1);
        this.notifyDataSetChanged();
    }

    public void clearAllItems(){
        mFragmentList.clear();
        this.notifyDataSetChanged();
    }

    public void updateItem(int position, Fragment fragment){
        mFragmentList.set(position, fragment);
        notifyDataSetChanged();
    }

    @Override
    public int getItemPosition(Object object) {
        if (mFragmentList.contains(object)) return mFragmentList.indexOf(object);
        else return POSITION_NONE;
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFrag(Fragment fragment) {
        mFragmentList.add(fragment);
        notifyDataSetChanged();
    } 
}

Note: Above adapter has no support for tab layouts, so feel free to adjust it to fit your needs

Usage:

 mAdapter = new CodebaseFragmentPagerAdapter(getSupportFragmentManager());
 mViewPager.setAdapter(mAdapter);

 mAdapter.addFrag(FragmentExample.newInstance());
Ivan Milisavljevic
  • 2,048
  • 2
  • 13
  • 21
  • That's a good suggestion. The reason I kept the fab in the MainActivity is because I have a collapsingtoolbar which hides the fab if it's placed in the bottom right corner of a fragment. I'm gonna try and play with that layout instead. – Mark F Mar 14 '17 at 15:54
  • If you want to hide the fab on scroll you can create a layout with structure similar to this not 100% sure but i think it should work – Ivan Milisavljevic Mar 14 '17 at 16:08