I have a screen with 3 tabs, a ViewPager below with 3 Fragments and a Floating Action Button in bottom-right corner.
When 1st tab is current tab then I want to show the FAB in bottom-right corner. When 2nd tab is current tab then I want to show the FAB in bottom-centre. When 3rd tab is current tab then I want to hide the FAB.
The translate animation from bottom-right to bottom-centre or vice versa should happen as the view pager scrolls i.e. on the basis of scroll amount.
Below is what I have tried.
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
ViewCompat.animate(mFAB)
.translationX(-translate)
.withLayer()
.setDuration(0)
.setInterpolator(new LinearInterpolator())
.start();
}
@Override
public void onPageSelected(int position) {
mTabLayout.getTabAt(position).select();
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
Is this the best way to do this? If yes what should be the value of translate variable?
Please help me in implementing this.
For reference you can checkout Android Lollipop Call application. The FAB to show the dialer animates in similar manner. For 1st tab its in bottom-right then for middle tab it comes in the centre. This is exactly what I want.
The easiest way to do that would be for example like this:
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
final int width = mViewPager.getWidth();
if (position == 0) { // represents transition from page 0 to page 1 (horizontal shift)
int translationX = (int) ((-(width - mFab.getWidth()) / 2f) * positionOffset);
mFab.setTranslationX(translationX);
mFab.setTranslationY(0);
} else if (position == 1) { // represents transition from page 1 to page 2 (vertical shift)
int translationY = (int) (mFab.getHeight() * positionOffset);
mFab.setTranslationY(translationY);
mFab.setTranslationX(-(width - mFab.getWidth()) / 2f);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
Bare in mind that width
parameter should represent the width of the screen (I assumed that the ViewPager
fills the width of the screen (so I assigned width = mViewPager.getWidth()
).
You also didnt exactly say in what way you want your FAB
to be hidden. So I just translated it vertically. You could also use setScaleX(...)
and setScaleY(...)
.
Edit:
The (step) value of the changed parameter should be calculated using the following method (Let's call it - for future references - formula 1
):
// formula 1
value = targetValue - ((targetValue - initialValue) * (1.0f - offset));
where offset
represents a parameter that changes (within range [0f; 1f]
). So in your case offset
is positionOffset
argument of the onPageScrolled
method.
Let's analyze the transition between pages 0 and 1 (of your case; position==0
):
FAB
horizontally, so you will be modifying the translationX
paramenter.FAB
is anchored at the bottom-right corner (e.g. with layout_gravity="bottom|right"
)FAB
is the proper position of your animation for NOT scrolled page 0. Therefore the the initialValue
of the translationX
for your animation is 0
initialValue = 0;
FAB
to the center of the screen. Given the screen width as a variable width
you can calculate the proper targetValue
for the FAB
shift to the center of the screen. It's equal to half of the screen width subtracted by half of the FAB
width. And since you're starting from the right corner, this value be negative (``)targetValue = -(width - mFab.getWidth()) / 2f;
initialValue
parameter is 0
, you can simplify the formula 1
to (will be referenced as formula 2
):// formula 2
value = targetValue * offset;
targetValue
you end up with this (formula 2
with calculated targetValue
and positionOffset
instead of offset
):value = (-(width - mFab.getWidth()) / 2f) * positionOffset;
Which is exactly what I used to move FAB
from the initial position (bottom|right
) to the center of the screen (horizontally).
I went through a similar process in calculating the desired step value for the translationY
in the transition between page 1 and 2.
What you need to do is do the same thing for any future steps. Think about initialValue
and targetValue
of the animated parameters, insert calculated values into the formula 1
and see if it works as desired.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With