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
.
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.
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.