【问题标题】:Translate animation for recyclerview and textview not smooth翻译 recyclerview 和 textview 的动画不流畅
【发布时间】:2016-03-24 02:22:54
【问题描述】:

我想在Toolbar下方显示一个TextView,以防有新事件进入。它应该从Toolbar下方向下滑动,出现1-2秒然后向上滑动再次。在TextView 下方是RecyclerView,在GridLayout 中订购了几件商品。

为此,我使用TranslateAnimation 让动画再次向上滑动:

TranslateAnimation animate = new TranslateAnimation(0, 0, 0, -tvStatus.getHeight());
animate.setDuration(1000);
animate.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
    }
    @Override
    public void onAnimationEnd(Animation animation) {
        tvStatus.setVisibility(View.GONE);
    }
    @Override
    public void onAnimationRepeat(Animation animation) {
    }
});
tvStatus.startAnimation(animate);

TextView 本身的滑动动画效果很好,但 RecyclerView 的动画效果不太好。 TextView 再次向上滑动,直到它被隐藏,并有一小段时间的间隙。

然后ReclerView就跳起来了,看起来不太好看。

我的问题是:TextView开始向上滑动时,如何调整我的代码以使RecylerView也向上滑动?

编辑 - 解决方案:

我调整了我的解决方案,包括来自Francescs answer 的输入。我解决了没有翻译的动画,只是通过改变视图的高度。

状态栏扩展方法:

public void expand() {
                    //set Visible
                    tvStatus.setVisibility(View.VISIBLE);
                    mAnimator = slideAnimator(0, mHeight);
                    mAnimator.setDuration(600);
                    mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
                    mAnimator.start();
}

折叠状态栏的方法:

private void collapse() {


        int finalHeight = tvStatus.getHeight();
                    ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
                    mAnimator.setDuration(500);
                    mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
                    mAnimator.addListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            tvStatus.setVisibility(View.GONE);
                        }
                    });
                    mAnimator.start();
}

价值动画师:

private ValueAnimator slideAnimator(int start, int end) {

        ValueAnimator animator = ValueAnimator.ofInt(start, end);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //Update Height
                int value = (Integer) valueAnimator.getAnimatedValue();
                ViewGroup.LayoutParams layoutParams = tvStatus.getLayoutParams();
                layoutParams.height = value;
                tvStatus.setLayoutParams(layoutParams);
            }
        });
        return animator;
}

onCreate中调用measureTextHeight()方法获取TextView高度:

public void measureTextHeight() {
        tvStatus.setVisibility(View.VISIBLE);
        tvStatus.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                mHeight = tvStatus.getHeight();
                if (mHeight > 0) {
                    tvStatus.getViewTreeObserver().removeOnPreDrawListener(this);
                    tvStatus.setVisibility(View.GONE);
                    return false;
                }
                return true;
            }
        });
    }

【问题讨论】:

    标签: android animation android-recyclerview translate-animation


    【解决方案1】:

    您还需要为 TextView 的布局参数设置动画,而不仅仅是翻译。添加它并与您的翻译动画并行运行。确保在开始动画之前知道文本视图的高度(如果文本视图不可见,您可能需要使用预绘制侦听器):

    final ViewGroup.LayoutParams layoutParams = mTextView.getLayoutParams();
    mTextView.setVisibility(View.VISIBLE);
    ValueAnimator anim = ValueAnimator.ofInt(mTextView.getHeight());
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            int val = (Integer) valueAnimator.getAnimatedValue();
            layoutParams.height = val;
            mTextView.setLayoutParams(layoutParams);
        }
    });
    anim.setDuration(1000);
    anim.start(); 
    

    编辑:

    要测量文本视图的高度,使其在您的布局中可见,然后添加一个 onPreDrawListener 来膨胀您的布局:

    private void measureTextHeight() {
        mTextView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                mTextViewHeight = mTextView.getHeight();
                if (mTextViewHeight > 0) {
                    mTextView.getViewTreeObserver().removeOnPreDrawListener(this);
                    mTextView.setTranslationY(-mTextViewHeight);
                    mTextView.setVisibility(View.GONE);
                    return false;
                }
                return true;
            }
        });
    }
    

    现在你有了文本视图的高度,所以你可以使用上面的函数来显示它。要隐藏它,请执行以下操作:

    final ViewGroup.LayoutParams layoutParams = mTextView.getLayoutParams();
    mTextView.setVisibility(View.VISIBLE);
    ValueAnimator anim = ValueAnimator.ofInt(mTextView.getHeight());
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            int val = (Integer) valueAnimator.getAnimatedValue();
            layoutParams.height = mTextViewHeight - val;
            mTextView.setLayoutParams(layoutParams);
        }
    });
    anim.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationCancel(Animator animation) {
            mTextView.setVisibility(View.GONE);
        }
    
        @Override
        public void onAnimationEnd(Animator animation) {
            mTextView.setVisibility(View.GONE);
        }
    });
    anim.setDuration(1000);
    anim.start();
    

    请记住,这需要与您的翻译动画并行运行,因此您可以使用动画组将它们一起运行。

    【讨论】:

    • 非常感谢您的快速回复,我会立即查看:) val 的值是多少? (layoutParams.height = val)
    • 我根据您的建议调整了我的解决方案,并且向下滑动动画有效,但如果之前视图不可见,则向上滑动无效。这如何与预绘制侦听器一起使用?我试过使用globalListenerpost 一样测量高度并使视图再次不可见,但addOnGlobalLayoutListener 只是有时被调用,而不是每次调用。
    • 更新了模式细节。
    • 感谢您的回复!恐怕我还是做错了,高度总是保持 0 :( 我在用 Butterknife 绑定视图之后在 onCreate 中调用你的方法(在不可能之前),它仍然总是返回 0。:( @ 987654328@
    • 确保textview的可见性在布局中是可见的,或者在添加predraw listener之前调用mTextView.setVisibility(View.VISIBLE)。
    猜你喜欢
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-30
    • 2010-11-07
    • 2017-07-01
    • 1970-01-01
    相关资源
    最近更新 更多