简体   繁体   中英

Translate animation for recyclerview and textview not smooth

I want to show a TextView below the Toolbar , which should appear in case there is a new event coming in. It should slide down from below the Toolbar , appear for 1-2secs and then slide up again. Below the TextView is a RecyclerView with several items ordered in a GridLayout .

使用 textview 和 recyclerview 进行布局

To achieve this, I'm using a TranslateAnimation to let the animation slide up again:

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

The sliding animation of the TextView itself is working fine, but the RecyclerView doesn't animate so well. The TextView slides up again until it is hidden and there is a gap for a short time. textview 消失后的间隙

And then the ReclerView just jumps up, which doesn't look very nice.

My question is: How can I adjust my code to make the RecylerView slide up as well when the TextView starts to slide up?

EDIT - Solution:

I adjusted my solution including the input from Francescs answer . I solved the animation without a translation, just by changing the height of the view.

Method to expand statusbar:

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

Method to collapse statusbar:

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

Value Animator:

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

measureTextHeight() method called in onCreate to get TextView height:

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

You need to animate the layout params of your TextView as well, not just the translation. Add this and run it in parallel to your translation animation. Make sure you know the text view height before starting the animation (you may need to use a predraw listener if the textview is invisible):

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(); 

Edit:

to measure the text view's height, make it visible in your layout, then add an onPreDrawListener where you inflate your layout:

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

Now you have the height of the text view, so you show it using the function above. To hide it, you do this:

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();

Remember that this needs to run in parallel to your translation animation, so you could use an animator set to run them together.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM