Show and hide a View with a slide up/down animation
I have a LinearLayout
that I want to show or hide with an Animation
that pushes the layout upwards or downwards whenever I change its visibility.
I've seen a few samples out there but none of them suit my needs.
I have created two xml files for the animations but I do not know how to start them when I change the visibility of a LinearLayout
.
Solution 1:
With the new animation API that was introduced in Android 3.0 (Honeycomb) it is very simple to create such animations.
Sliding a View
down by a distance:
view.animate().translationY(distance);
You can later slide the View
back to its original position like this:
view.animate().translationY(0);
You can also easily combine multiple animations. The following animation will slide a View
down by its height and fade it in at the same time:
// Prepare the View for the animation
view.setVisibility(View.VISIBLE);
view.setAlpha(0.0f);
// Start the animation
view.animate()
.translationY(view.getHeight())
.alpha(1.0f)
.setListener(null);
You can then fade the View
back out and slide it back to its original position. We also set an AnimatorListener
so we can set the visibility of the View
back to GONE
once the animation is finished:
view.animate()
.translationY(0)
.alpha(0.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setVisibility(View.GONE);
}
});
Solution 2:
I was having troubles understanding an applying the accepted answer. I needed a little more context. Now that I have figured it out, here is a full example:
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button myButton;
View myView;
boolean isUp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myView = findViewById(R.id.my_view);
myButton = findViewById(R.id.my_button);
// initialize as invisible (could also do in xml)
myView.setVisibility(View.INVISIBLE);
myButton.setText("Slide up");
isUp = false;
}
// slide the view from below itself to the current position
public void slideUp(View view){
view.setVisibility(View.VISIBLE);
TranslateAnimation animate = new TranslateAnimation(
0, // fromXDelta
0, // toXDelta
view.getHeight(), // fromYDelta
0); // toYDelta
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
}
// slide the view from its current position to below itself
public void slideDown(View view){
TranslateAnimation animate = new TranslateAnimation(
0, // fromXDelta
0, // toXDelta
0, // fromYDelta
view.getHeight()); // toYDelta
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
}
public void onSlideViewButtonClick(View view) {
if (isUp) {
slideDown(myView);
myButton.setText("Slide up");
} else {
slideUp(myView);
myButton.setText("Slide down");
}
isUp = !isUp;
}
}
activity_mail.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.slideview.MainActivity">
<Button
android:id="@+id/my_button"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
android:onClick="onSlideViewButtonClick"
android:layout_width="150dp"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/my_view"
android:background="#a6e1aa"
android:orientation="vertical"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="200dp">
</LinearLayout>
</RelativeLayout>
Notes
- Thanks to this article for pointing me in the right direction. It was more helpful than the other answers on this page.
- If you want to start with the view on screen, then don't initialize it as
INVISIBLE
. - Since we are animating it completely off screen, there is no need to set it back to
INVISIBLE
. If you are not animating completely off screen, though, then you can add an alpha animation and set the visibility with anAnimatorListenerAdapter
. - Property Animation docs
Solution 3:
Now visibility change animations should be done via Transition API
which available in support (androidx) package. Just call TransitionManager.beginDelayedTransition method with Slide transition then change visibility of the view.
import androidx.transition.Slide;
import androidx.transition.Transition;
import androidx.transition.TransitionManager;
private void toggle(boolean show) {
View redLayout = findViewById(R.id.redLayout);
ViewGroup parent = findViewById(R.id.parent);
Transition transition = new Slide(Gravity.BOTTOM);
transition.setDuration(600);
transition.addTarget(R.id.redLayout);
TransitionManager.beginDelayedTransition(parent, transition);
redLayout.setVisibility(show ? View.VISIBLE : View.GONE);
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="play" />
<LinearLayout
android:id="@+id/redLayout"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#5f00"
android:layout_alignParentBottom="true" />
</RelativeLayout>
Check this answer with another default and custom transition examples.
Solution 4:
Easiest solution: set android:animateLayoutChanges="true"
on the container holding your views.
To put it into some context: If you have a layout like below, all visibility changes to the views in this container will be animated automatically.
<LinearLayout android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
>
<Views_which_change_visibility>
</LinearLayout>
You can find more details about this on Animating Layout Changes - Android Developer