3

Problem

I want to create viewpager with 2 fragments in one Activity. This fragments have different menu options, and one fragment is nested - by clicking listview item, opens same fragment with new data (replace(), addToBackStack()), but viewpager don't replacing correctly (when I do transaction.replace(R.id.viewpager, new TwoFragment()).

I used this answer - https://stackoverflow.com/a/18020219/5576117, but I have different menu options, and menu options inflated from Fragment Container.

As a result if I create a new Fragment (as container) I just pass boolean extra isContainer to fragment and this works. But now activity call wrong onOptionsItemSelected method (call from fragment2, when in viewpager selected fragment1).

My code

MainActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {    
     ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
     viewPager.addOnPageChangeListener(this);
     setupViewPager(viewPager);

     TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
     tabLayout.setupWithViewPager(viewPager);
}

private void setupViewPager(ViewPager viewPager) {
     viewPager.setOffscreenPageLimit(2);
     mAdapter = new MainViewPagerAdapter(getSupportFragmentManager());

     TwoFragment fragment = new TwoFragment();
     Bundle args = new Bundle(1);
     args.putBoolean(TwoFragment.ISCONTAINER_EXTRA, true);
     fragment.setArguments(args);
     mAdapter.addFragment(fragment, "TAB1");
     mAdapter.addFragment(new OneFragment(), "TAB2");
}

OneFragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.fragment_one, container, false);
     setHasOptionsMenu(true);
     return view;
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
     super.onCreateOptionsMenu(menu, inflater);
     menu.clear();
     inflater.inflate(R.menu.menu_one, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
     // This method not called then this fragment selected in viewpager
     return true;
}

TwoFragment:

@Override
public void onCreate(Bundle savedInstanceState) {
   Bundle extras = getArguments();
   if (extras != null && extras.containsKey(ISCONTAINER_EXTRA)) {
       isContainer = extras.getBoolean(ISCONTAINER_EXTRA);
   }

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   if (isContainer) {
       setHasOptionsMenu(false);
       FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
       transaction.replace(R.id.clRoot, new TwoFragment()).commit();
       return inflater.inflate(R.layout.fragment_two, container, false);
    }
    View view = inflater.inflate(R.layout.fragment_two, container, false);
    setHasOptionsMenu(true);
    // Other actions
    return view;
    }

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    menu.clear();
    inflater.inflate(R.menu.menu_two, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // This method called then always
    switch (item.getItemId()) {
        case android.R.id.home:
            getFragmentManager().popBackStack();
            break;
        case R.id.action_settings:
            startActivity(new Intent(getActivity(), SettingsActivity.class));
            break;
        case R.id.action_exit:
            Intent homeIntent = new Intent(Intent.ACTION_MAIN);
            homeIntent.addCategory(Intent.CATEGORY_HOME);
            homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(homeIntent);
            break;
    }
    return true;
}

Question

How can I accomplish this without the use of third-party libraries?

P.S: sorry for my bad english.

Community
  • 1
  • 1
Mamykin Andrey
  • 1,352
  • 10
  • 13

2 Answers2

1

if i did understand you probably and your only issue is now that the option menu is not being displaying probably you could do this

 pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
        @Override public void onPageSelected(int position) {
            supportInvalidateOptionsMenu();
        }
    });

this will re-invalidate the menu each time you select a page in the fragment and you can do the same every time you replace a fragment by calling

((getActivity())AppCompatActivity).supportInvalidateOptionsMenu();

which will invalidate the menu on every replaced fragment.

Kosh
  • 6,140
  • 3
  • 36
  • 67
  • Thanks for response, I tried this, but also called wrong onOptionsItemSelected method. – Mamykin Andrey Nov 22 '15 at 12:30
  • can you please explain more by called wrong onOptionItemSelected? because if your menu is in the nestedFragment you'll have to implement onOptionsItemSelected within the nested fragment, not within the activity – Kosh Nov 22 '15 at 12:47
  • Sorry for waiting, I meant what when in viewpager selected fragment2 called onOptionsItemSelected from fragment1. – Mamykin Andrey Nov 22 '15 at 14:15
0

Answer here: https://tausiq.wordpress.com/2014/06/06/android-multiple-fragments-stack-in-each-viewpager-tab/ (In this case used viewpagerindicator library, but it can easily be replaced by tablayout).

Main idea: create root fragment, and in this fragment place your viewpager, tablayout and other fragments. All works fine.

Mamykin Andrey
  • 1,352
  • 10
  • 13