Ich habe eine LinearLayout
, die ich mit einer Animation
anzeigen oder ausblenden möchte, die das Layout bei jeder Änderung der Sichtbarkeit nach oben oder unten schiebt.
Ich habe ein paar Beispiele da draußen gesehen, aber keine davon entspricht meinen Bedürfnissen.
Ich habe zwei XML-Dateien für die Animationen erstellt, weiß jedoch nicht, wie ich sie starten soll, wenn ich die Sichtbarkeit einer LinearLayout
ändere.
Mit der neuen Animations-API, die in Android 3.0 (Honeycomb) eingeführt wurde, ist es sehr einfach, solche Animationen zu erstellen.
View
um eine Strecke nach unten schieben:
view.animate().translationY(distance);
Sie können das View
später wie folgt in die ursprüngliche Position zurückschieben:
view.animate().translationY(0);
Sie können auch mehrere Animationen einfach kombinieren. Die folgende Animation bewegt ein View
um seine Höhe nach unten und blendet es gleichzeitig ein:
// 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);
Sie können dann View
wieder ausblenden und in die ursprüngliche Position zurückschieben. Wir haben auch eine AnimatorListener
gesetzt, damit wir die Sichtbarkeit der View
wieder auf GONE
setzen können, sobald die Animation abgeschlossen ist:
view.animate()
.translationY(0)
.alpha(0.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setVisibility(View.GONE);
}
});
Ich hatte Probleme, die Anwendung der akzeptierten Antwort zu verstehen. Ich brauchte etwas mehr Kontext. Nun, da ich es herausgefunden habe, hier ein vollständiges Beispiel:
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>
INVISIBLE
.INVISIBLE
zurücksetzen. Wenn Sie jedoch nicht vollständig außerhalb des Bildschirms animieren, können Sie eine Alpha-Animation hinzufügen und die Sichtbarkeit mit einer AnimatorListenerAdapter
einstellen.Einfachste Lösung: Setzen Sie Android:animateLayoutChanges="true"
in den Container, in dem sich Ihre Ansichten befinden.
Um es in einen Kontext zu bringen: Wenn Sie ein Layout wie unten haben, werden alle Sichtbarkeitsänderungen der Ansichten in diesem Container automatisch animiert.
<LinearLayout Android:id="@+id/container"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:animateLayoutChanges="true"
>
<Views_which_change_visibility>
</LinearLayout>
Weitere Informationen hierzu finden Sie unter Animieren von Layoutänderungen - Android Developer
Sie können die korrekte Animation
starten, wenn sich die Sichtbarkeit der LinearLayout
ändert, indem Sie eine neue Unterklasse von LinearLayout
erstellen und setVisibility()
überschreiben, um die Animations
zu starten. Betrachten Sie so etwas:
public class SimpleViewAnimator extends LinearLayout
{
private Animation inAnimation;
private Animation outAnimation;
public SimpleViewAnimator(Context context)
{
super(context);
}
public void setInAnimation(Animation inAnimation)
{
this.inAnimation = inAnimation;
}
public void setOutAnimation(Animation outAnimation)
{
this.outAnimation = outAnimation;
}
@Override
public void setVisibility(int visibility)
{
if (getVisibility() != visibility)
{
if (visibility == VISIBLE)
{
if (inAnimation != null) startAnimation(inAnimation);
}
else if ((visibility == INVISIBLE) || (visibility == GONE))
{
if (outAnimation != null) startAnimation(outAnimation);
}
}
super.setVisibility(visibility);
}
}
if (filter_section.getVisibility() == View.GONE) {
filter_section.animate()
.translationY(filter_section.getHeight()).alpha(1.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
filter_section.setVisibility(View.VISIBLE);
filter_section.setAlpha(0.0f);
}
});
} else {
filter_section.animate()
.translationY(0).alpha(0.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
filter_section.setVisibility(View.GONE);
}
});
}
Kotlin
Basierend auf Suragch 's answer , ist dies ein eleganter Weg mit der Erweiterung View:
fun View.slideUp(duration: Int = 500) {
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, this.height.toFloat(), 0f)
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
fun View.slideDown(duration: Int = 500) {
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, 0f, this.height.toFloat())
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
Und wo immer Sie es verwenden möchten, brauchen Sie nur myView.slideUp()
oder myView.slideDown()
sie können jede Ansicht oder jedes Layout mit dem untenstehenden Code in der Android-App nach oben und unten verschieben
boolean isClicked=false;
LinearLayout mLayoutTab = (LinearLayout)findViewById(R.id.linearlayout);
if(isClicked){
isClicked = false;
mLayoutTab.animate()
.translationYBy(120)
.translationY(0)
.setDuration(getResources().getInteger(Android.R.integer.config_mediumAnimTime));
}else{
isClicked = true;
mLayoutTab.animate()
.translationYBy(0)
.translationY(120)
.setDuration(getResources().getInteger(Android.R.integer.config_mediumAnimTime));
}
Verwenden Sie diese Klasse:
public class ExpandCollapseExtention {
public static void expand(View view) {
view.setVisibility(View.VISIBLE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(widthSpec, heightSpec);
ValueAnimator mAnimator = slideAnimator(view, 0, view.getMeasuredHeight());
mAnimator.start();
}
public static void collapse(final View view) {
int finalHeight = view.getHeight();
ValueAnimator mAnimator = slideAnimator(view, finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationEnd(Animator animator) {
view.setVisibility(View.GONE);
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
mAnimator.start();
}
private static ValueAnimator slideAnimator(final View v, int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
layoutParams.height = value;
v.setLayoutParams(layoutParams);
}
});
return animator;
}
}
Hier ist meine Lösung. Holen Sie sich einfach einen Verweis auf Ihre Ansicht und rufen Sie diese Methode auf:
public static void animateViewFromBottomToTop(final View view){
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
final int TRANSLATION_Y = view.getHeight();
view.setTranslationY(TRANSLATION_Y);
view.setVisibility(View.GONE);
view.animate()
.translationYBy(-TRANSLATION_Y)
.setDuration(500)
.setStartDelay(200)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(final Animator animation) {
view.setVisibility(View.VISIBLE);
}
})
.start();
}
});
}
Keine Notwendigkeit, etwas anderes zu tun =)
Ich hatte einen Eckfall, bei dem die Höhe meiner Ansicht noch zero
war ...
import Android.animation.Animator;
import Android.animation.AnimatorListenerAdapter;
import Android.view.View;
public final class AnimationUtils {
public static void slideDown(final View view) {
view.animate()
.translationY(view.getHeight())
.alpha(0.f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// superfluous restoration
view.setVisibility(View.GONE);
view.setAlpha(1.f);
view.setTranslationY(0.f);
}
});
}
public static void slideUp(final View view) {
view.setVisibility(View.VISIBLE);
view.setAlpha(0.f);
if (view.getHeight() > 0) {
slideUpNow(view);
} else {
// wait till height is measured
view.post(new Runnable() {
@Override
public void run() {
slideUpNow(view);
}
});
}
}
private static void slideUpNow(final View view) {
view.setTranslationY(view.getHeight());
view.animate()
.translationY(0)
.alpha(1.f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
view.setVisibility(View.VISIBLE);
view.setAlpha(1.f);
}
});
}
}
Sie können die einfachen drei Codezeilen verwenden, um die Animation anzuzeigen ...
//getting the hiding view by animation
mbinding.butn.setOnClickListener {
val SlideOutLeft = AnimationUtils.loadAnimation(this, R.anim.slide_out_left)
simplelayout.visibility = View.INVISIBLE
simplelayout.startAnimation(SlideOutLeft)
val SlideInRight = AnimationUtils.loadAnimation(applicationContext, R.anim.slide_in_right)
animation1.visibility = View.VISIBLE
animation1.startAnimation(SlideInRight)
}
//again unhide the view animation
mbinding.buttn.setOnClickListener {
val SlideInLeft=AnimationUtils.loadAnimation(this,R.anim.slide_in_left)
//set the layout
simplelayout.visibility=View.VISIBLE
simplelayout.startAnimation(SlideInLeft)
val SlideOutRight=AnimationUtils.loadAnimation(this,R.anim.slide_out_right)
animation1.visibility=View.INVISIBLE
animation1.startAnimation(SlideOutRight)
}
Animationen zur Änderung der Sichtbarkeit sollten jetzt über Transition API
erfolgen, der im Support-Paket (androidx) verfügbar ist. Rufen Sie einfach TransitionManager.beginDelayedTransition mit Slide Transition auf und ändern Sie dann die Sichtbarkeit der Ansicht.
import androidx.transition.Slide;
import androidx.transition.Transition;
import androidx.transition.TransitionManager;
private void toggle() {
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>
Überprüfen Sie diese Antwort mit anderen Beispielen für Standard- und benutzerdefinierte Übergänge.
Suragchs Antwort in Kotlin. Das hat bei mir funktioniert.
class MainActivity : AppCompatActivity() {
var isUp: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myView: View = findViewById(R.id.my_view)
var myButton: Button = findViewById(R.id.my_button)
//Initialize as invisible
myView.visibility = View.INVISIBLE
myButton.setText("Slide up")
isUp = false
}
fun View.slideUp(duration: Int = 500){
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, this.height.toFloat(), 0f)
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
fun View.slideDown(duration: Int = 500) {
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, 0f, this.height.toFloat())
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
fun onSlideViewButtonClick(view: View){
if(isUp){
my_view.slideDown()
my_button.setText("Slide Up")
}
else{
my_view.slideUp()
my_button.setText("Slide Down")
}
isUp = !isUp
}
}