0

I'd like to be able to not allow switching to one of my 3 fragments in my custom FragmentPagerAdapter when certain conditions are met. Unfortunately I failed to find any help.

I'd prefer to not remove and re-add the fragment (item 0), as this criterium can change inside the FragmentActivity any time and I'd need the fragment to be able to receive and handle messages.

Any suggestions? Please ask if something's unclear.

Edit: Sharing some code

Main activity:

@Override
protected void onResume() {
    super.onResume();
    ...
    _sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(), this, cardnumber, pin);
    _viewPager = (ViewPager) findViewById(R.id.pager);
    _viewPager.setAdapter(_sectionsPagerAdapter);
    _viewPager.setOnPageChangeListener(_sectionsPagerAdapter);
    _viewPager.setCurrentItem(1);
    _viewPager.setOffscreenPageLimit(2);

This seems a bit rude, but it works

@Override
public Fragment getItem(int position) {

    Fragment fragment = null;
    Bundle args = new Bundle();

    switch (position) {
    case CUSTOMER_DETAILS_PAGE:
        // fragment = _fragments.get(TRLIST_PAGE);
        fragment = new UserDetailFragment();
        args.putString("TAG", "details");
        break;
    case BALANCE_PAGE:
        // fragment = _fragments.get(BALANCE_PAGE);
        fragment = new BalanceFragment();
        args.putString("TAG", "balance");
        break;
    case TRLIST_PAGE:
        // fragment = _fragments.get(TRLIST_PAGE);
        fragment = new TrListFragment();
        args.putString("TAG", "trlist");
        break;
    default:
        break;
    }

    _listeners.put(position, (MyTabSelectedListener) fragment);
    // fragment = (Fragment) _listeners.get(position);
    args.putString("cardnumber", _cardnumber);
    args.putString("pin", _pin);
    fragment.setArguments(args);

    return fragment;
}

I want to limit access to the CUSTOMER_DETAILS_PAGE when it would be empty anyway.

Lance Toth
  • 430
  • 3
  • 17
  • Share some code, so that we can understand your problem – Ichigo Kurosaki Jan 29 '15 at 12:30
  • Added some code, hope it helps. – Lance Toth Jan 29 '15 at 12:41
  • 1
    Well, if you want to do it in a hacky way, you can try to override the touch handling logic in the `ViewPager` to prohibit swiping to that page depending on a custom flag. This will be somewhat complicated to implement, specially if you want to retain the over-scrolling effect. Alternatively, you can add/remove the item from your `PagerAdapter` implementation (you can just detach it from the `FragmentManager` instead of removing). You will have to use a custom `PagerAdapter` implementation as described in the following answer: http://stackoverflow.com/a/23967701/3153792 – corsair992 Jan 29 '15 at 13:59
  • I think I'm getting somewhere with your suggestion. Thanks! – Lance Toth Jan 29 '15 at 15:17

1 Answers1

0

After reading corsair992-s answer here https://stackoverflow.com/a/23967701/3153792 and looking at the CWAC-Pager source code here https://github.com/commonsguy/cwac-pager I managed to find what I was looking for.

The key was to change the getItemPosition function (which I didn't even use before) to get the TAG argument (set in getItem) from the fragments and identify them that way:

@Override
public int getItemPosition(Object item) {
    Fragment fragment = (Fragment) item;
    String title = fragment.getArguments().getString("TAG");
    int position = tabs.indexOf(title);
    if (position >= 0) {
        return position;
    } else {
        return POSITION_NONE;
    }

First I define tags for each tab and a list to hold them in order of appearance:

public static final String CUSTOMER_DETAILS_PAGE = "detail";
public static final String BALANCE_PAGE = "balance";
public static final String TRLIST_PAGE = "trlist";

List<String> tabs = new ArrayList<String>();

Afterwards, I add them in the constructor in the original order:

tabs.add(CUSTOMER_DETAILS_PAGE);
tabs.add(BALANCE_PAGE);
tabs.add(TRLIST_PAGE);

When I need to hide a tab, I just remove it from the list and notify the adapter:

public void disableUserDetail() {
    tabs.remove(tabs.indexOf(CUSTOMER_DETAILS_PAGE));
    notifyDataSetChanged();
}

My fragment specifically goes to the left side (the beginning) but it would be easy to change:

public void enableUserDetail() {
    tabs.add(0, CUSTOMER_DETAILS_PAGE);
    notifyDataSetChanged();
}

I had to change getItem and getPageTitle to use the tabs list and TAG constants as identifier (which I also include as arguments for getItemPosition):

@Override
public Fragment getItem(int position) {
    String id = tabs.get(position);
    Fragment fragment = null;
    Bundle args = new Bundle();
    if (id.equals(CUSTOMER_DETAILS_PAGE)) {
        fragment = new UserDetailFragment();
    args.putString("TAG", CUSTOMER_DETAILS_PAGE);
...

@Override
public CharSequence getPageTitle(int position) {
    Locale l = Locale.getDefault();
    String id = tabs.get(position);

     if (id.equals(CUSTOMER_DETAILS_PAGE)) {
        return _ctx.getString(R.string.title_section1).toUpperCase(l);
...
Community
  • 1
  • 1
Lance Toth
  • 430
  • 3
  • 17