1

I have an Activity with a ViewPager, which displays three different Fragments. Everything is inside a CoordinatorLayout. What I basically did is the same as in this answer: FAB animation with viewpager/tabslider

I don't want to have the FAB in the first Fragment, so I set the FAB's visibility to GONE in the layout and show/hide it only when the 2nd Fragment is selected. This part actually works fine.

However, when the Activity is first created(or the screen is rotated) the FAB pops up on the first Fragment for a quick moment, which is really annoying. When I replace the CoordinatorLayout with something else, the FAB stays hidden when it should.

I'm using the design support library 23.0.1. The cheesesquare sample is having the same issue, when the FAB is set to be gone.

Can someone suggest a workaround for this? I couldn't find the sources for the CoordinatorLayout, so I couldn't look for a reason why this happens.

Community
  • 1
  • 1
MatF
  • 1,728
  • 2
  • 14
  • 31

1 Answers1

2

Here's the code I came up with (and no, in advance, it is not perfect, nor is it optimal. But it does work. Feel free to optimize as you see fit). I will come back and clean this up to a more elegant degree at a later date, but in interest of getting you an answer to work with quickly, here you go.

private ViewPager viewPager;
private SparseArray<View.OnClickListener> floatingActionButtonOnClickListeners;
private FloatingActionButton floatingActionButton;

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

    viewPager = (ViewPager) findViewById(R.id.viewpager);
    floatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
    setupTabs();
    setFABOnClickListeners();
}

@Override
protected void onResume() {
    super.onResume();
    setFabVisibility(viewPager.getCurrentItem());
}

private void setupTabs() {
    FragmentStatePagerAdapter adapter = new FragmentStatePagerAdapter(getSupportFragmentManager());
    viewPager.setAdapter(adapter);
    tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);

    viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            setFabVisibility(viewPager.getCurrentItem());
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            switch (state) {
                case ViewPager.SCROLL_STATE_DRAGGING:
                    floatingActionButton.hide();
                    break;
            }
        }
    });
}

private void setFabVisibility(int position) {
    View.OnClickListener floatingActionButtonClickListener = floatingActionButtonClickListeners.get(position);

    floatingActionButton.setOnClickListener(floatingActionButtonClickListener);

    if (floatingActionButtonClickListener == null) {
        hideFabForever();
    } else {
        showFabNormally();
    }
}

private void hideFabForever() {
    ((CoordinatorLayout.LayoutParams) floatingActionButton.getLayoutParams()).setBehavior(new FloatingActionButton.Behavior());
    floatingActionButton.hide();
}

private void showFabNormally() {
    ((CoordinatorLayout.LayoutParams) floatingActionButton.getLayoutParams()).setBehavior(new ScrollAwareFABBehavior(this, null, new ScrollBehaviorListener() {
        @Override
        public void onAnimatedOut(View view) {
        }

        @Override
        public void onAnimatedIn(View view) {
        }
    }));

    floatingActionButton.show();
}

private void setFABOnClickListeners() {
    if (floatingActionButtonOnClickListeners == null) {
        floatingActionButtonOnClickListeners = new SparseArray<>();
    }

    // An example, but populate the SparseArray with the position of the tab
    // that should have a FAB. This will be used to indicate that the FAB 
    // should be visible on that position.
    floatingActionButtonOnClickListeners.put(0, new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO handle click
        }
    });

     floatingActionButtonOnClickListeners.put(2, new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO handle click
        }
    });

    floatingActionButtonOnClickListeners.put(4, new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO handle click
        }
    });
}

A couple of notes:

showFabNormally();

and

hideFabForever();

are ONLY necessary if you have a custom behavior that messes up the visibility of the FAB. In this case, I have a custom ScrollAwareFABBehavior that causes the FAB to disappear when scrolling down and reappear when scrolling back up. You can opt to just call

floatingActionButton.show();

and

floatingActionButton.hide();

respectively. I left the behavior code in there to demonstrate how to handle this so that one FAB can be used for all tabs, even if a custom behavior affects its visibility.

Chantell Osejo
  • 1,456
  • 15
  • 25
  • Thank you for your input. Your example is almost the same as mine and didn't directly help me. However I was able to find the real problem: I hadn't set the layout anchor for the FAB! With the anchor set to the viewpager, the FAB doesn't pop up on the first fragment. – MatF Oct 01 '15 at 06:14
  • Good! I think the key for me was the onResume() bit of code. It handles the visibility check so that the FAB stays the way it should for the tab. – Chantell Osejo Oct 01 '15 at 19:19
  • That shouldn't even be a problem, but google doesn't fix it: https://code.google.com/p/android/issues/detail?id=27526 – MatF Oct 02 '15 at 10:09