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.