Animacja zmiany koloru tła widoku na Androidzie

Jak animować zmianę koloru tła widoku na Androidzie?

Na przykład:

Mam widok z czerwonym kolorem tła. Kolor tła widoku zmienia się na niebieski. Jak zrobić płynne przejście między kolorami?

Jeśli nie można tego zrobić z widokami, alternatywa będzie mile widziana.

Author: Peter Mortensen, 2010-04-10

12 answers

Znalazłem (całkiem dobre) rozwiązanie tego problemu!

Możesz użyć TransitionDrawable aby to osiągnąć. Na przykład, w pliku XML w folderze drawable możesz napisać coś w stylu:

<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- The drawables used here can be solid colors, gradients, shapes, images, etc. -->
    <item android:drawable="@drawable/original_state" />
    <item android:drawable="@drawable/new_state" />
</transition>

Następnie, w Twoim XML dla rzeczywistego widoku będziesz odwoływać się do tego przejścia w atrybucie android:background.

W tym momencie możesz zainicjować Przejście W swoim kodzie na polecenie wykonując:

TransitionDrawable transition = (TransitionDrawable) viewObj.getBackground();
transition.startTransition(transitionTime);

Lub uruchomić Przejście W odwrotnej kolejności przez wywołanie:

transition.reverseTransition(transitionTime);

Zobacz Roman ' s answer dla innego rozwiązania wykorzystującego API animacji właściwości, które nie było dostępne w momencie, gdy odpowiedź została pierwotnie opublikowana.

 323
Author: idolize,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:35

Możesz użyć nowego API animacji właściwości do kolorowej animacji:

int colorFrom = getResources().getColor(R.color.red);
int colorTo = getResources().getColor(R.color.blue);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(250); // milliseconds
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animator) {
        textView.setBackgroundColor((int) animator.getAnimatedValue());
    }

});
colorAnimation.start();

Dla wstecznej kompatybilności z Androidem 2.x Użyj dziewięciu starych bibliotek androidów od Jake ' a Whartona.

Metoda getColor została przestarzała w Androidzie m, więc masz dwa wyjścia:

  • Jeśli używasz biblioteki wsparcia, musisz zastąpić getColor wywołania przez:

    ContextCompat.getColor(this, R.color.red);
    
  • Jeśli nie używasz biblioteki wsparcia, musisz zastąpić wywołania getColor z:

    getColor(R.color.red);
    
 419
Author: Roman Minenok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-12 08:56:47

W zależności od tego, jak widok otrzymuje swój kolor tła i jak uzyskać kolor docelowy, istnieje kilka różnych sposobów, aby to zrobić.

Pierwsze dwa wykorzystują framework Android Property Animation .

Użyj animatora obiektu jeśli:

  • twój Widok ma kolor tła zdefiniowany jako wartość argb w pliku xml.
  • Twój widok miał wcześniej ustawiony kolor przez view.setBackgroundColor()
  • twój Widok ma kolor tła zdefiniowany w drawable, który nie definiuje żadnych dodatkowych właściwości, takich jak promienie obrysu lub rogu.
  • twój Widok ma kolor tła zdefiniowany w drawable i chcesz usunąć dodatkowe właściwości, takie jak promienie obrysu lub rogu, pamiętaj, że usunięcie dodatkowych właściwości nie będzie animowane.

Animator obiektu działa poprzez wywołanie view.setBackgroundColor, które zastępuje zdefiniowany drawable, chyba że jest to instancja ColorDrawable, którą rzadko jest. Oznacza to, że każdy dodatkowe właściwości tła z rysowalnego obrysu lub narożników zostaną usunięte.

Użyj animatora wartości jeśli:

  • twój Widok ma kolor tła zdefiniowany w drawable, który również ustawia właściwości, takie jak promienie obrysu lub rogu i chcesz zmienić go na nowy kolor, który jest ustalany podczas pracy.

Użyj przejścia drawable jeśli:

  • Twój widok powinien przełączyć się między dwoma rysowalnymi, które zostały zdefiniowane przed rozmieszczeniem.

Miałem pewne problemy z wydajnością z przejściówkami, które działają podczas otwierania szuflady, której nie byłem w stanie rozwiązać, więc jeśli napotkasz jakieś nieoczekiwane jąkanie, możesz napotkać ten sam błąd, co ja.

Będziesz musiał zmodyfikować przykład animatora wartości, jeśli chcesz użyć StateLists drawable lub LayerLists drawable , w przeciwnym razie zostanie on zawieszony na linii final GradientDrawable background = (GradientDrawable) view.getBackground();.

Obiekt Animator:

Definicja widoku:

<View
    android:background="#FFFF0000"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

Utwórz i użyj ObjectAnimator w ten sposób.

final ObjectAnimator backgroundColorAnimator = ObjectAnimator.ofObject(view,
                                                                       "backgroundColor",
                                                                       new ArgbEvaluator(),
                                                                       0xFFFFFFFF,
                                                                       0xff78c5f9);
backgroundColorAnimator.setDuration(300);
backgroundColorAnimator.start();
Można również wczytać definicję animacji z xml za pomocą AnimatorInflater, tak jak robi to XMight w Android objectAnimator animate backgroundColor układu

Animator Wartości:

Definicja widoku:

<View
    android:background="@drawable/example"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

Definicja Drawable:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#FFFFFF"/>
    <stroke
        android:color="#edf0f6"
        android:width="1dp"/>
    <corners android:radius="3dp"/>

</shape>

Tworzenie i używanie ValueAnimator jak to:

final ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(),
                                                           0xFFFFFFFF,
                                                           0xff78c5f9);

final GradientDrawable background = (GradientDrawable) view.getBackground();
currentAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(final ValueAnimator animator) {
        background.setColor((Integer) animator.getAnimatedValue());
    }

});
currentAnimation.setDuration(300);
currentAnimation.start();

Przejście drawable:

Definicja widoku:

<View
    android:background="@drawable/example"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

Definicja Drawable:

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <solid android:color="#FFFFFF"/>
            <stroke
                android:color="#edf0f6"
                android:width="1dp"/>
            <corners android:radius="3dp"/>
        </shape>
    </item>

    <item>
        <shape>
            <solid android:color="#78c5f9"/>
            <stroke
                android:color="#68aff4"
                android:width="1dp"/>
            <corners android:radius="3dp"/>
        </shape>
    </item>
</transition>

Użyj przejścia w ten sposób:

final TransitionDrawable background = (TransitionDrawable) view.getBackground();
background.startTransition(300);

Animacje można odwrócić, wywołując .reverse() na wystąpieniu animacji.

Istnieje kilka innych sposobów tworzenia animacji, ale te trzy są prawdopodobnie najczęstsze. Zazwyczaj używam ValueAnimator.

 121
Author: Mattias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:45

Możesz utworzyć animator obiektów. Na przykład mam targetView i chcę zmienić kolor tła:

int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
    .setDuration(duration)
    .start();
 45
Author: ademar111190,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-21 10:38:11

Jeśli chcesz mieć taką kolorową animację,

Tutaj wpisz opis obrazka

Ten kod ci pomoże:

ValueAnimator anim = ValueAnimator.ofFloat(0, 1);   
anim.setDuration(2000);

float[] hsv;
int runColor;
int hue = 0;
hsv = new float[3]; // Transition color
hsv[1] = 1;
hsv[2] = 1;
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {

        hsv[0] = 360 * animation.getAnimatedFraction();

        runColor = Color.HSVToColor(hsv);
        yourView.setBackgroundColor(runColor);
    }
});

anim.setRepeatCount(Animation.INFINITE);

anim.start();
 17
Author: RBK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-24 09:16:10

Innym łatwym sposobem, aby to osiągnąć, jest wykonanie zaniku przy użyciu AlphaAnimation.

  1. Make your view a ViewGroup
  2. Dodaj do niego widok potomny w indeksie 0, z wymiarami układu match_parent
  3. nadaj dziecku takie samo tło jak pojemnik
  4. Zmiana tła kontenera na kolor docelowy
  5. Usuń dziecko za pomocą AlphaAnimation.
  6. Usuń dziecko po zakończeniu animacji (za pomocą AnimationListener)
 11
Author: Stephane JAIS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-26 13:08:14

Jest to metoda, której używam w podstawowej aktywności do zmiany tła. Używam GradientDrawables wygenerowanych w kodzie, ale można je dostosować do własnych potrzeb.

    protected void setPageBackground(View root, int type){
        if (root!=null) {
            Drawable currentBG = root.getBackground();
            //add your own logic here to determine the newBG 
            Drawable newBG = Utils.createGradientDrawable(type); 
            if (currentBG==null) {
                if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){
                    root.setBackgroundDrawable(newBG);
                }else{
                    root.setBackground(newBG);
                }
            }else{
                TransitionDrawable transitionDrawable = new TransitionDrawable(new Drawable[]{currentBG, newBG});
                transitionDrawable.setCrossFadeEnabled(true);
                if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){
                     root.setBackgroundDrawable(transitionDrawable);
                }else{
                    root.setBackground(transitionDrawable);
                }
                transitionDrawable.startTransition(400);
            }
        }
    }

Update: W przypadku, gdy ktoś uruchomi ten sam problem, który znalazłem, z jakiegoś powodu na Androidzie setCrossFadeEnabled(true) spowodować niepożądany biały efekt, więc musiałem przełączyć się na jednolity kolor dla

 8
Author: scottyab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-01 14:29:18

Najlepszy sposób użycia ValueAnimator i ColorUtils.blendARGB

 ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
 valueAnimator.setDuration(325);
 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {

              float fractionAnim = (float) valueAnimator.getAnimatedValue();

              view.setColorBackground(ColorUtils.blendARGB(Color.parseColor("#FFFFFF")
                                    , Color.parseColor("#000000")
                                    , fractionAnim));
        }
});
valueAnimator.start();
 6
Author: Rasoul Miri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-24 12:37:27

Oto Ładna funkcja, która na to pozwala:

public static void animateBetweenColors(final View viewToAnimateItBackground, final int colorFrom, final int colorTo,
        final int durationInMs) {
    final ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
    colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
        ColorDrawable colorDrawable = new ColorDrawable(colorFrom);

        @Override
        public void onAnimationUpdate(final ValueAnimator animator) {
            colorDrawable.setColor((Integer) animator.getAnimatedValue());
            viewToAnimateItBackground.setBackgroundDrawable(colorDrawable);
        }
    });
    if (durationInMs >= 0)
        colorAnimation.setDuration(durationInMs);
    colorAnimation.start();
}
 4
Author: android developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-30 08:30:36

Odpowiedź jest udzielana na wiele sposobów. Możesz również użyć ofArgb(startColor,endColor) z ValueAnimator.

Dla API > 21:

int cyanColorBg = ContextCompat.getColor(this,R.color.cyan_bg);
int purpleColorBg = ContextCompat.getColor(this,R.color.purple_bg);

ValueAnimator valueAnimator = ValueAnimator.ofArgb(cyanColorBg,purpleColorBg);
        valueAnimator.setDuration(500);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator valueAnimator) {
                   relativeLayout.setBackgroundColor((Integer)valueAnimator.getAnimatedValue());
              }
        });
        valueAnimator.start();
 4
Author: Palak Darji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-03 04:06:59

Odkryłem, że implementacja używana przez ArgbEvaluator w kodzie źródłowym Androida najlepiej sprawdza się przy przechodzeniu kolorów. Przy użyciu HSV, w zależności od dwóch kolorów, Przejście przeskakiwało zbyt wiele odcieni dla mnie. Ale ta metoda Nie.

Jeśli próbujesz po prostu animować, użyj ArgbEvaluator z ValueAnimator zgodnie z sugestią tutaj:

ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animator) {
        view.setBackgroundColor((int) animator.getAnimatedValue());
    }

});
colorAnimation.start();

Jeśli jednak jesteś taki jak ja i chcesz powiązać swoje przejście z jakimś gestem użytkownika lub inną wartością przekazaną z wejścia, ValueAnimator nie jest zbyt pomocne (chyba że kierujesz się na API 22 i wyżej, w takim przypadku możesz użyć ValueAnimator.setCurrentFraction() metoda). Przy kierowaniu poniżej API 22, zawiń kod znaleziony w ArgbEvaluator Kod źródłowy w Twojej własnej metodzie, jak pokazano poniżej:

public static int interpolateColor(float fraction, int startValue, int endValue) {
    int startA = (startValue >> 24) & 0xff;
    int startR = (startValue >> 16) & 0xff;
    int startG = (startValue >> 8) & 0xff;
    int startB = startValue & 0xff;
    int endA = (endValue >> 24) & 0xff;
    int endR = (endValue >> 16) & 0xff;
    int endG = (endValue >> 8) & 0xff;
    int endB = endValue & 0xff;
    return ((startA + (int) (fraction * (endA - startA))) << 24) |
            ((startR + (int) (fraction * (endR - startR))) << 16) |
            ((startG + (int) (fraction * (endG - startG))) << 8) |
            ((startB + (int) (fraction * (endB - startB))));
}

I używaj go jak chcesz.

 2
Author: fahmy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:48

Dodaj folder animator do folderu res . (nazwa musi być animator ). Dodaj plik zasobów programu animator. Na przykład res / animator / fade.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="backgroundColor"
        android:duration="1000"
        android:valueFrom="#000000"
        android:valueTo="#FFFFFF"
        android:startOffset="0"
        android:repeatCount="-1"
        android:repeatMode="reverse" />
</set>

Wewnątrz Activity java file, call this

View v = getWindow().getDecorView().findViewById(android.R.id.content);
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.fade);
set.setTarget(v);
set.start();
 2
Author: canbax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-10 11:36:28