Android,view.bringToFront()无法在ViewPager

时间:2015-11-23 21:48:26

标签: android android-viewpager android-view bringtofront

我在this示例之后建立了一个ViewPager模型,我正在实施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);
        }
    }
}

并且效果很好,正如上面链接中显示的深度页面变换器动画所示。

但是,它目前的工作方式是右侧的视图始终低于左侧的视图。向右滚动时,视图来自下方。向左滚动使当前视图位于新视图下方,该视图将滑入顶部。

我想要做的是让当前视图始终位于顶部,并且新视图(左侧或右侧)从后面/下方进入。

我尝试过添加

view.bringToFront();

if(position <= 0)块,但没有任何变化。我也尝试过添加

view.bringToFront();
view.invalidate();

view.bringToFront();
((View)view.getParent()).invalidate();

一切都无济于事。我可以找到similar SO posts所采用的相同方法,但所有这些方法都接受了答案和评论,说它们有效。但我的不是!

如何将当前视图始终作为最顶层视图,无论滑动方向如何?

编辑1 - 附加详细信息

正如评论中所提到的,我需要知道是向左还是向左滑动以获得同样的动画。

ViewPager只有三个视图,它们显示为基于this帖子的VerticalViewPager

在PageTransformer中,我有以下内容:

    @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);
        }

    }

其中firstsecondthird的类型为View并设置在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 ...
    }
}

它有点被黑客攻击,但效果很好,并且正是我正在寻找的功能。除bringToFront之外无效的事情。但是,无论我在原始帖子中使用transformPage代码,还是在此编辑中使用更全面的版本,它都无效。

仍然不确定如何使second(即三者的中间视图)始终位于顶部。我甚至尝试过通用

second.bringToFront();

位于方法的顶部,但仍然没有。

编辑2

刚试过view.setZ()但遇到了以下错误:

  

java.lang.NoSuchMethodError:android.view.View.setZ

这个选项也是如此。

编辑3 - 解决方案

要解决此问题,请参阅下面的答案(使用getChildDrawingOrder)。

话虽如此,我仍然无法让bringToFront工作,并且如果你能弄明白的话,我会乐意选择你的答案。

提前再次感谢。

3 个答案:

答案 0 :(得分:1)

知道了!万一你遇到同样的问题......

我有一个自定义类:

public class VerticalViewPager extends ViewPager

这是实现transformPage方法的同一个类。在ViewPager的构造函数中,设置以下内容:

setChildrenDrawingOrderEnabled(true);

您需要覆盖以下方法:

@Override
protected int getChildDrawingOrder(int childCount, int i) {
    switch(i){
        case 0: return 1;
        case 1: return 2;
        case 2: return 0;
    }

    return super.getChildDrawingOrder(childCount, i);
}

此方法允许您选择绘制ViewPager的子视图的顺序。由于我只有三个视图,我只需要担心案例0-2。

无论你以哪种观点最后(在我的情况下,第二/中间视图),都将是顶视图。

方法参数int i是绘图迭代,它是

for(i = 0; i < childCount; i++)

并返回绘图顺序。

因此,只需选择您希望绘制视图的顺序,然后选择它。

请注意,这仅适用于将一个视图置于顶部。如果您有三个以上的观看次数,或者总是希望当前观看次数最多,那么您必须找到一些其他方式来动态更改顶部视图。

编辑 - 附加信息

如果您覆盖getChildDrawingOrder,则可能会在ViewPager破坏屏幕外视图时收到 nullpointerexceptions 。如果您的观看次数很少,可以添加:

viewPager.setOffscreenPageLimit(2);

其中参数是您拥有的视图数量减去1.这将防止这些视图被破坏。

答案 1 :(得分:0)

对于那些寻找动态尺寸的人,我找到了适用于后KitKat版本的解决方案。基本上我所做的是增加当前中心视图的高度。 (我还在为棒棒糖前解决方案工作)

这是我的代码,将OnPageChangeListener设置为ViewPager,并在OnPageSelected方法中

     @Override public void onPageSelected(int position) {

      //Counter for loop
      int count = 0;
      int PAGER_LOOP_THRESHOLD = 2;
      if (position >= PAGER_LOOP_THRESHOLD) {
        count = position - PAGER_LOOP_THRESHOLD;
      }
      do {
        Fragment fragment = (Fragment) adapter.instantiateItem(pager, count);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
            && fragment.getView() != null) {

          //If it's current center position, increase view's elevation. Otherwise, we reduce elevation
          if (count == position) {
            fragment.getView().setElevation(8.0f);
          }
          else {
            fragment.getView().setElevation(0.0f);
          }
        }
        count++;
      } while (count < position + PAGER_LOOP_THRESHOLD);
    }

答案 2 :(得分:0)

你可以设置:

mViewPager.setPageTransformer(false, new DepthPageTransformer());