I have a ViewPager modelled after this example, where I am implementing ViewPager.PageTransformer
:
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // (0,1]
view.setAlpha(1 - position);
view.setTranslationX(view.getWidth() * -position);
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
view.setAlpha(0);
}
}
}
and it works great, just as shown in the Depth Page Transformer animation shown in the link above.
But, the way it currently works is that views to the right are always below the views on the left. As you scroll right, the views come from below. Scrolling left has the current view going below the new view, which slides in on top.
What I'd like to do is have the current view ALWAYS be on top, and for the new view (left or right) to come in from behind/below.
I've tried adding
view.bringToFront();
to the if(position <= 0)
block, but nothing changes. I've also tried adding
view.bringToFront();
view.invalidate();
and
view.bringToFront();
((View)view.getParent()).invalidate();
all to no avail. These are the same approaches taken by similar SO posts that I can find, but all of them have accepted answers and comments saying they work. But mine doesn't!
How can I have the current view ALWAYS be the top-most view, regardless of swipe direction?
EDIT 1 - ADDITIONAL DETAILS
As was mentioned in the comments, I'd need to know if swiped right or left to get the same animation going both ways.
The ViewPager only has three views, and they are presented as a VerticalViewPager
, based off this post.
Within the PageTransformer, I have the following:
@Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
view.setAlpha(0);
}
else if(position <= 0){
if(view == first){
view.setAlpha(1 - Math.abs(position));
view.setTranslationX(view.getWidth() * -position);
view.setTranslationY(0);
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
}else if(view == second){
view.setAlpha(1);
view.setTranslationX(view.getWidth() * -position);
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
}else if(view == third){
// Never happen
}
}
else if (position <= 1) { // [0,1]
if(view == first){
// Never happen
}else if(view == second){
view.setAlpha(1);
view.setTranslationX(view.getWidth() * -position);
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
}else if(view == third){
view.setAlpha(1 - position);
view.setTranslationX(view.getWidth() * -position);
view.setTranslationY(0);
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
}
} else { // (1,+Infinity]
view.setAlpha(0);
}
}
Where first
, second
and third
are type View
and set inside of the PagerAdapter:
@Override
public View instantiateItem(ViewGroup container, int position) {
if(position == 0){
... stuff ...
vvp.first = img;
... stuff ...
}else if(position == 1){
... stuff ...
vvp.second = img;
... stuff ...
}else if(position == 2){
... stuff ...
vvp.third = img;
... stuff ...
}
}
It's a little hacked together, but works great and gets exactly the functionality I'm looking for. EXCEPT for the bringToFront
thing that isn't working. But it doesn't work whether I use the transformPage
code in the original post, or the more comprehensive version in this edit.
Still unsure how to make second
(i.e. the middle view of the three) always on top. I even tried a generic
second.bringToFront();
at the top of the method, but still nothing.
EDIT 2
Just tried view.setZ()
but met the following error:
java.lang.NoSuchMethodError: android.view.View.setZ
So that option's out as well.
EDIT 3 - SOLUTION
For my solution to this problem, please see answer below (using getChildDrawingOrder
).
That being said, I still cannot get bringToFront
to work, and will happily select your answer as the chosen one if you can figure it out.
Thanks again in advance.