web-dev-qa-db-fra.com

Animer le changement de couleur de fond sur Android

Comment animer le changement de couleur d'arrière-plan d'une vue sur Android?

Par exemple:

J'ai une vue avec une couleur de fond rouge. La couleur d'arrière-plan de la vue devient bleue. Comment puis-je faire une transition en douceur entre les couleurs?

Si cela ne peut pas être fait avec des vues, une alternative sera la bienvenue.

302
hpique

J'ai fini par trouver une (très bonne) solution à ce problème!

Vous pouvez utiliser un TransitionDrawable pour accomplir cela. Par exemple, dans un fichier XML du dossier pouvant être dessiné, vous pouvez écrire quelque chose comme:

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

Ensuite, dans votre XML pour la vue réelle, vous référenceriez cette TransitionDrawable dans l'attribut Android:background.

À ce stade, vous pouvez lancer la transition dans votre code sur commande en procédant comme suit:

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

Ou exécutez la transition en sens inverse en appelant:

transition.reverseTransition(transitionTime);

Voir réponse de Roman pour une autre solution utilisant l'API Property Animation, qui n'était pas disponible au moment où cette réponse a été publiée.

349
idolize

Vous pouvez utiliser new Property Animation Api pour l’animation couleur:

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();

Pour assurer la compatibilité ascendante avec Android 2.x, utilisez bibliothèque Nine Old Androids de Jake Wharton.

La méthode getColor était obsolète dans Android M, vous avez donc deux choix:

  • Si vous utilisez la bibliothèque de support, vous devez remplacer les appels getColor par:

    ContextCompat.getColor(this, R.color.red);
    
  • si vous n'utilisez pas la bibliothèque de support, vous devez remplacer les appels getColor par:

    getColor(R.color.red);
    
465
Roman Minenok

En fonction de la couleur d'arrière-plan de votre vue et de la couleur cible, il existe différentes façons de procéder.

Les deux premiers utilisent le cadre Android Property Animation .

Utilisez un Object Animator si:

  • La couleur d'arrière-plan de votre vue est définie en tant que valeur argb dans un fichier XML.
  • La couleur de votre vue a déjà été définie par view.setBackgroundColor()
  • La couleur d'arrière-plan de votre vue est définie dans un dessin que NE FAUT PAS définit les propriétés supplémentaires telles que le rayon de trait ou le coin.
  • La couleur d'arrière-plan de votre vue est définie dans un dessin et vous souhaitez supprimer toutes les propriétés supplémentaires, telles que les contours ou les rayons d'angle. N'oubliez pas que la suppression des propriétés supplémentaires ne sera pas animée.

L’animateur d’objets fonctionne en appelant view.setBackgroundColor qui remplace le dessin défini sauf s’il s’agit d’une instance de ColorDrawable, ce qui est rarement le cas. Cela signifie que toutes les propriétés d'arrière-plan supplémentaires pouvant être dessinées, comme les traits ou les coins, seront supprimées.

Utilisez un Value Animator si:

  • La couleur d'arrière-plan de votre vue est définie dans un dessin qui définit également des propriétés telles que le rayon ou le rayon des angles ET que vous souhaitez changer pour une nouvelle couleur définie lors de l'exécution.

Utilisez un Transition drawable si:

  • Votre vue doit basculer entre deux dessinables définis avant le déploiement.

J'ai eu quelques problèmes de performances avec les tirables de Transition qui fonctionnent pendant que j'ouvre un DrawerLayout que je n'ai pas pu résoudre, donc si vous rencontrez un bégaiement inattendu, vous rencontrerez peut-être le même bogue que le mien.

Vous devrez modifier l'exemple de Value Animator si vous souhaitez utiliser un StateLists drawable ou un LayerLists drawable , sinon il se plantera sur la ligne final GradientDrawable background = (GradientDrawable) view.getBackground();.

Object Animator :

Voir la définition:

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

Créez et utilisez une ObjectAnimator comme celle-ci.

final ObjectAnimator backgroundColorAnimator = ObjectAnimator.ofObject(view,
                                                                       "backgroundColor",
                                                                       new ArgbEvaluator(),
                                                                       0xFFFFFFFF,
                                                                       0xff78c5f9);
backgroundColorAnimator.setDuration(300);
backgroundColorAnimator.start();

Vous pouvez également charger la définition d'animation à partir d'un fichier xml à l'aide d'un AnimatorInflater, comme XMight le fait dans Android objectAnimator animate backgroundColor of Layout

Value Animator :

Voir la définition:

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

Définition tirable:

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

Créez et utilisez un ValueAnimator comme ceci:

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();

Transition dessinable :

Voir la définition:

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

Définition tirable:

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

Utilisez le TransitionDrawable comme ceci:

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

Vous pouvez inverser les animations en appelant .reverse() sur l'instance d'animation.

Il y a d'autres façons de faire des animations mais ces trois sont probablement les plus courantes. J'utilise généralement un ValueAnimator.

127
Mattias

Vous pouvez faire un animateur d'objet. Par exemple, j'ai un targetView et je veux changer votre couleur de fond:

int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
    .setDuration(duration)
    .start();
53
ademar111190

Si vous voulez une animation couleur comme celle-ci,

Enter image description here

ce code vous aidera:

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();
19
RBK

le meilleur moyen consiste à utiliser ValueAnimator et 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.setBackgroundColor(ColorUtils.blendARGB(Color.parseColor("#FFFFFF")
                                    , Color.parseColor("#000000")
                                    , fractionAnim));
        }
});
valueAnimator.start();
11
Rasoul Miri

Un autre moyen simple d'y parvenir consiste à effectuer un fondu à l'aide d'AlphaAnimation.

  1. Faites de votre vue un ViewGroup
  2. Ajoutez une vue enfant à l'index 0, avec les dimensions de présentation match_parent.
  3. Donnez à votre enfant le même fond que le conteneur
  4. Passer en arrière-plan du conteneur à la couleur cible
  5. Estomper l'enfant avec AlphaAnimation.
  6. Supprime l'enfant une fois l'animation terminée (à l'aide d'un AnimationListener)
11
Stephane JAIS

C'est la méthode que j'utilise dans une activité de base pour changer de fond. J'utilise GradientDrawables généré dans le code, mais pourrait être adapté en conséquence.

    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);
            }
        }
    }

pdate: Si quelqu'un rencontre le même problème que j'ai trouvé, pour quelque raison que ce soit sur Android <4.3, en utilisant setCrossFadeEnabled(true), un effet de blanc indésirable m'a obligé à changer en couleur unie pour <4,3 en utilisant la méthode @Roman Minenok ValueAnimator indiquée ci-dessus.

9
scottyab

La réponse est donnée à bien des égards. Vous pouvez également utiliser ofArgb(startColor,endColor) sur ValueAnimator.

pour 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();
5
Palak Darji

Voici une fonction intéressante qui permet ceci:

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
android developer

ajouter un dossier animateur dans le dossier res. (le nom doit être animateur). Ajoutez un fichier de ressources d'animateur. Par exemple 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>

Dans le fichier Activity Java, appelez-le.

View v = getWindow().getDecorView().findViewById(Android.R.id.content);
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.fade);
set.setTarget(v);
set.start();
3
canbax

J'ai constaté que l'implémentation utilisée par ArgbEvaluator dans le code source Android fonctionne mieux dans la transition des couleurs. Lorsque vous utilisez le HSV, selon les deux couleurs, la transition sautait trop de teintes pour moi. Mais cette méthode ne fonctionne pas.

Si vous essayez simplement d’animer, utilisez ArgbEvaluator avec ValueAnimator comme suggéré ici :

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();

Toutefois, si vous êtes comme moi et souhaitez associer votre transition à un geste de l'utilisateur ou à une autre valeur transmise à partir d'une entrée, le paramètre ValueAnimator ne vous sera pas d'une grande aide (à moins que vous ne cibliez l'API 22 ou une version ultérieure, auquel cas vous pouvez utiliser la méthode ValueAnimator.setCurrentFraction() ). Lorsque vous ciblez sous API 22, encapsulez le code trouvé dans ArgbEvaluator code source dans votre propre méthode, comme indiqué ci-dessous:

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))));
}

Et utilisez-le comme vous le souhaitez.

2
fahmy