Fade In Fade Out Android Animation w Javie

148

Chcę mieć 2-sekundową animację ImageView, która spędza 1000 ms na zanikaniu, a następnie 1000 ms na zanikaniu.

Oto, co mam do tej pory w moim konstruktorze ImageView:

Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setDuration(1000);

Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setStartOffset(1000);
fadeOut.setDuration(1000);

AnimationSet animation = new AnimationSet(true);
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
this.setAnimation(animation);

Kiedy uruchamiam tę animację, nic się nie pojawia. Jednak kiedy usuwam jedną z animacji alfa, zachowanie działa zgodnie z oczekiwaniami.

Rzeczy, których już próbowałem:

  • Każdej możliwej kombinacji setFillBefore, setFillAfteri setFillEnabled.
  • Dodawanie LinearInterpolatordo AnimationSet.
oracz
źródło
1
Tak, możesz pojawiać się i znikać obrazy! Ten samouczek powinien załatwić sprawę. sankarganesh-info-exchange.blogspot.com/2011/04/…
Adam Storm
W tym samouczku opisano metodę używającą XML. Czy wiesz, jak osiągnąć to samo za pomocą Javy?
oracz
Cóż, nie jestem obok mojego komputera do programowania, więc nie mogę przetestować tego kodu, ale możesz ustawić atrybuty xml w java. to jest oryginalny kod: android: interpolator = "@ android: anim / Accelerate_interpolator" android: fromAlpha = "0.0" android: toAlpha = "1.0" android: duration = "300" /> \ n więc prawdopodobnie możesz MyTween.setDurationg (300) MyTween.fromAlpha (0.0) MyTween (1.0)
Adam Storm,

Odpowiedzi:

258

Zrozumiałem swój problem. Ostatecznie rozwiązanie zostało oparte na interpolatorach.

Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); //add this
fadeIn.setDuration(1000);

Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); //and this
fadeOut.setStartOffset(1000);
fadeOut.setDuration(1000);

AnimationSet animation = new AnimationSet(false); //change to false
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
this.setAnimation(animation);


Jeśli używasz Kotlin

val fadeIn = AlphaAnimation(0f, 1f)
fadeIn.interpolator = DecelerateInterpolator() //add this
fadeIn.duration = 1000

val fadeOut = AlphaAnimation(1f, 0f)
fadeOut.interpolator = AccelerateInterpolator() //and this
fadeOut.startOffset = 1000
fadeOut.duration = 1000

val animation = AnimationSet(false) //change to false
animation.addAnimation(fadeIn)
animation.addAnimation(fadeOut)
this.setAnimation(animation)
oracz
źródło
1
A co jeśli chcesz zrobić 5 lub 6 stopni wejścia / wyjścia, z naprawdę małymi opóźnieniami, takimi jak 100 dla każdego, czy możesz użyć czegoś takiego? Próbowałem, ale to nie jest naprawdę płynne. Celem było zasymulowanie na przykład żarówki, która nie działałaby prawidłowo i migotała.
Chayy
spróbuj nazwać this.setAnimation w pętli
Jonathan
Myślałem, że znikam ostatni bg img i fad w obecnym, ale ta odpowiedź inspiruje mnie, że muszę tylko zniknąć w bieżącym bg img i zaniknąć bieżący, ponieważ AlphaAnimation nie może zniknąć / zgasić dwóch różnych obrazów .
macio,
8
Myślę, że nie potrzebujesz dwóch niezależnych animacji ... Myślę, że możesz mieć jedną animację i ustawić parametr: fadeInOut.setRepeatMode (Animation.REVERSE);
RoundSparrow hilltx
Po drugie: jeśli chcesz powtórzyć, nie musisz dzwonić w pętli, jak powiedział @jonney. użyj fadeInOut.setRepeatCount (6) - zmień 6 na liczbę powtórzeń. Znacznie mniej narzutów, aby umożliwić natywnemu kodowi C ++ w systemie Android to wszystko zamiast wywoływania pętli Java.
RoundSparrow hilltx
137

Wiem, że już na to odpowiedziano, ale .....

<?xml version="1.0" encoding="utf-8"?> 
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="1.0" 
    android:toAlpha="0.0" 
    android:duration="1000"    
    android:repeatCount="infinite" 
    android:repeatMode="reverse"
    />

Szybki i łatwy sposób na szybkie wprowadzanie i wyłączanie z powtarzaniem samego siebie. Cieszyć się

EDYCJA : W swojej aktywności dodaj to:

yourView.startAnimation(AnimationUtils.loadAnimation(co‌​ntext, R.anim.yourAnimation));
Konrad Winkowski
źródło
6
+1 Ponieważ z tą odpowiedzią mógłbym zrobić zabezpieczenie wejścia, zanikania i zanikania (po prostu ustawiając repeCount = "2"). Nie mogłem łączyć animacji zgodnie z akceptowaną odpowiedzią.
ElYeante,
1
Po zadeklarowaniu tego alphazasobu, jak mogę z niego korzystać? Dzięki
zozelfelfo
1
zozelfelfo to po prostu plik XML animacji, więc załaduj go do kodu, a następnie wywołaj startAnimation w dowolnym widoku, na który ma to wpłynąć.
Konrad Winkowski
@KonradWinkowski metoda startAnimation wymaga obiektu Animation jako argumentu! co mam do niego przekazać?
Ahmad Vatani
Dla tych, którzy szukają pełniejszej odpowiedzi: viewToAnimate.startAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_in_out)gdzie w folderze anim pod res. Znajduje się plik fade_in_out.xml.
Chris Knight
32
viewToAnimate.animate().alpha(1).setDuration(1000).setInterpolator(new DecelerateInterpolator()).withEndAction(new Runnable() {
    @Override
    public void run() {
        viewToAnimate.animate().alpha(0).setDuration(1000).setInterpolator(new AccelerateInterpolator()).start();
    }
}).start();
Witalij Zinczenko
źródło
4
Elegante for Marshmallow!
LETs
26

Oto moje rozwiązanie wykorzystujące AnimatorSet, które wydaje się być nieco bardziej niezawodne niż AnimationSet.

// Custom animation on image
ImageView myView = (ImageView)splashDialog.findViewById(R.id.splashscreenImage);

ObjectAnimator fadeOut = ObjectAnimator.ofFloat(myView, "alpha",  1f, .3f);
fadeOut.setDuration(2000);
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(myView, "alpha", .3f, 1f);
fadeIn.setDuration(2000);

final AnimatorSet mAnimationSet = new AnimatorSet();

mAnimationSet.play(fadeIn).after(fadeOut);

mAnimationSet.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        mAnimationSet.start();
    }
});
mAnimationSet.start();
TWilly
źródło
Musiałem użyć ObjectAnimator zamiast Animation, aby uzyskać działające rozwiązanie, ponieważ z jakiegoś powodu za każdym razem, gdy uruchamiałem AlphaAnimation, uruchamiało się ono dwukrotnie i powodowało dziwne migotanie.
Andrew Orobator
eleganckie rozwiązanie
Vlad
Cóż, jest już za późno, ale myślę, że może to pomóc w jakiejś życzliwej animacji przed ponownym użyciem jej w tym samym widoku ..
Bhavesh Moradiya
21

Inna alternatywa:

Nie ma potrzeby definiowania 2 animacji dla fadeIn i fadeOut . fadeOut jest odwrotnością fadeIn .

Możesz to zrobić za pomocą Animation.REVERSE w następujący sposób:

AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
alphaAnimation.setDuration(1000);
alphaAnimation.setRepeatCount(1);
alphaAnimation.setRepeatMode(Animation.REVERSE);
view.findViewById(R.id.imageview_logo).startAnimation(alphaAnimation);

potem onAnimationEnd :

alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
    @Override
        public void onAnimationStart(Animation animation) {
            //TODO: Run when animation start
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            //TODO: Run when animation end
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            //TODO: Run when animation repeat
        }
    });
MarsLudzie
źródło
12

Ponieważ wierzę w siłę XML (dla układów), jest to odpowiednik zaakceptowanej odpowiedzi , ale wyłącznie jako zasób animacji:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:fillAfter="true">
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:duration="1000" />
    <alpha
        android:fromAlpha="1"
        android:toAlpha="0"
        android:duration="1000"
        android:startOffset="1000"/>
</set>

fillAfterJest dla blaknięcie pozostać po zakończeniu animacji. Jak można się domyślić, interpolatorobsługuje interpolację animacji. Możesz także użyć innych typów interpolatorów, takich jak Linear lub Overshoot.

Pamiętaj, aby rozpocząć animację w swoim widoku:

yourView.startAnimation(AnimationUtils.loadAnimation(co‌​ntext, R.anim.fade));
DarkCygnus
źródło
@KGCybeX żadnego problemu, zadowolony, że mogłem pomóc :)
DarkCygnus
1
Bardzo pomocny i czysty. U mnie działa idealnie.
Fernando Barbosa
9

Oto, czego użyłem do zanikania / wyłączania widoków, mam nadzieję, że to komuś pomoże.

private void crossFadeAnimation(final View fadeInTarget, final View fadeOutTarget, long duration){
    AnimatorSet mAnimationSet = new AnimatorSet();
    ObjectAnimator fadeOut = ObjectAnimator.ofFloat(fadeOutTarget, View.ALPHA,  1f, 0f);
    fadeOut.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            fadeOutTarget.setVisibility(View.GONE);
        }

        @Override
        public void onAnimationCancel(Animator animation) {
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
        }
    });
    fadeOut.setInterpolator(new LinearInterpolator());

    ObjectAnimator fadeIn = ObjectAnimator.ofFloat(fadeInTarget, View.ALPHA, 0f, 1f);
    fadeIn.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            fadeInTarget.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationEnd(Animator animation) {}

        @Override
        public void onAnimationCancel(Animator animation) {}

        @Override
        public void onAnimationRepeat(Animator animation) {}
    });
    fadeIn.setInterpolator(new LinearInterpolator());
    mAnimationSet.setDuration(duration);
    mAnimationSet.playTogether(fadeOut, fadeIn);
    mAnimationSet.start();
}
Cristhian Escobar
źródło
Jakoś to jedyna odpowiedź, która obejmuje ustawienie widoczności, fajnie
Łukasz
8

AnimationSets nie wydaje się działać zgodnie z oczekiwaniami. W końcu zrezygnowałem i użyłem postDelayed () klasy Handler do sekwencjonowania animacji.

Richard
źródło
8

Jeśli używasz Animatora do tworzenia animacji, możesz

anim (katalog) -> fade_out.xml

<?xml version="1.0" encoding="UTF-8"?>
<objectAnimator
    android:propertyName="alpha"
    android:valueFrom="0"
    android:valueTo="1"
    xmlns:android="http://schemas.android.com/apk/res/android"/>

W java

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.fade_out);
animator.setTarget(the_view_you_want_to_animation);
animator.setDuration(1000);
animator.start();

Innym sposobem na zanikanie animacji za pomocą samego kodu java jest

ObjectAnimator fadeOut = ObjectAnimator.ofFloat(the_view_you_want_to_animation, "alpha",  1f, 0);
fadeOut.setDuration(2000);
fadeOut.start();
Phan Van Linh
źródło
w katalogu anim * not animator
kosas
4

Możesz także użyć animacjiListener, czegoś takiego:

fadeIn.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationEnd(Animation animation) {
        this.startAnimation(fadeout);
    }
});
Omid Aminiva
źródło
0

Bardzo podoba mi się rozwiązanie Witalija Zinczenki , ponieważ było krótkie.

Oto jeszcze krótsza wersja w kotlinie dla prostego zanikania

viewToAnimate?.alpha = 1f
viewToAnimate?.animate()
             ?.alpha(0f)
             ?.setDuration(1000)
             ?.setInterpolator(DecelerateInterpolator())
             ?.start()
Marc
źródło