【问题标题】:Android, view.bringToFront() not working in ViewPagerAndroid,view.bringToFront() 在 ViewPager 中不起作用
【发布时间】:2016-02-26 04:00:42
【问题描述】:

我有一个以 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);
        }
    }
}

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

但是,它目前的工作方式是 right 的视图总是低于 left 的视图。当您向右滚动时,视图来自下方。向左滚动使当前视图位于新视图下方,新视图滑入顶部。

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

我已经尝试添加

view.bringToFront();

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

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

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

一切都无济于事。这些与我能找到的similar SO posts 采用的方法相同,但他们都接受了答案,并且 cmets 说它们有效。但我的没有!

无论滑动方向如何,如何让当前视图始终位于最顶层?

编辑 1 - 附加细节

正如 cmets 中提到的,我需要知道是向右还是向左滑动才能获得双向的相同动画。

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

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

    }

其中firstsecondthirdView 类型并设置在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 工作,如果你能弄清楚,我很乐意选择你的答案作为所选答案。

再次提前致谢。

【问题讨论】:

    标签: android android-viewpager android-view bringtofront


    【解决方案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。这将防止这些视图被破坏。

    【讨论】:

      【解决方案2】:

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

      这是我的代码,在您的 ViewPager 和 OnPageSelected 方法中设置 OnPageChangeListener

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

      【讨论】:

        【解决方案3】:

        你可以设置:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-15
          • 1970-01-01
          • 1970-01-01
          • 2013-10-19
          • 1970-01-01
          • 2015-12-09
          相关资源
          最近更新 更多