web-dev-qa-db-fra.com

Faire pivoter une image avec une animation

The two states of the image

Ce que j'ai

J'ai une image de flèche (comme celle de gauche). Lorsque l'utilisateur clique dessus, il doit pivoter de 180 degrés avec une animation et doit ressembler à la bonne.

Ce que j'ai fait

private void rotate(float degree, final int toggleV) {

        final RotateAnimation rotateAnim = new RotateAnimation(0.0f, degree,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);

        rotateAnim.setDuration(500);
        toggle.startAnimation(rotateAnim);
        rotateAnim.setAnimationListener(new Animation.AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {


                if (toggleV == 1)
                    toggle.setImageResource(R.drawable.toggle_up);
                else
                    toggle.setImageResource(R.drawable.toggle_down);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }

Le problème

Je vois que l'animation fonctionne bien mais il y a un petit scintillement lors du réglage de l'image. Cela peut être dû au décalage horaire à la fin de l'animation et à la définition de l'image.

Comment puis-je supprimer ce problème de scintillement? Avez-vous une meilleure approche pour ce faire?

23
Aritra Roy

Tout d'abord, quelle est votre exigence minimale de SDK? Si c'est au moins Android 3.0, vous pouvez utiliser le nouveau framework d'animation et animer votre image avec quelque chose comme ceci:

imageView.animate().rotation(180).start();

À propos du scintillement: je ne réinitialiserais pas l'image source de l'ImageView après la rotation, je laisserais simplement l'original et m'assurerais que l'animation de rotation se remplit après l'animation, laissant l'image pivotée. Le scintillement est très probablement provoqué par le relais/redessin de la vue lors du changement de l'image source.

D'autres artefacts visuels (scintillement?) Peuvent être dus au fait que l'image pivotée d'origine et l'image statique pivotée peuvent différer de quelques pixels.

51

Si j'étais vous, j'utiliserais ViewPropertyAnimator (disponible depuis l'API 12). Sa syntaxe est plus simple IMO.
L'utilisation serait:

toggle.animate().rotation(0.5f);
4
Alex.F

Pourquoi n'utilisez-vous pas RotateAnimation?

créez un dossier nommé anim dans res et un fichier nommé rotator.xml dans res/anim.

<rotate xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:duration="400"
Android:fromDegrees="0"
Android:pivotX="50%"
Android:pivotY="50%"
Android:toDegrees="360"/>

Ici, une rotation complète sera effectuée en 4000 ms (4 secondes). Ajoutez maintenant une image PNG que vous souhaitez faire pivoter dans votre dossier dessinable. Ouvrez ensuite res/main.xml, après avoir supprimé le textView par défaut dans la mise en page, ajoutez une ImageView et un bouton dans la mise en page. Définissez la propriété src de ImageView comme votre nom de fichier de l'image ajoutée, par exemple Android: src = ”@ drawable/myimg” Ok, permet de modifier la classe principale. Dans le onClick () du bouton, ajoutez le code nécessaire pour exécuter l'animation. Vérifiez le code suivant.

public class AnimationActivity extends Activity {

    public ImageView  myImage ;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        myImage = (ImageView)findViewById(R.id.imageView1);
        final Animation myRotation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotator);
        ((Button)findViewById(R.id.button1)).setOnClickListener(new OnClickListener()    {
            @Override
            public void onClick(View arg0) {
                myImage.startAnimation(myRotation);
            }
        });
    }
}
2
Vinay Jayaram

Vous pouvez utiliser setFillAfter si vous souhaitez conserver l'état de votre animation.

1
Rajesh

Si vous souhaitez faire pivoter une image de 180 degrés dans le sens des aiguilles d'une montre.

private var isExpanded = true

private fun rotateImage(view: View) {
    val startAngle = if (isExpanded) 0f else 180f
    ObjectAnimator.ofFloat(view, View.ROTATION, startAngle, startAngle + 180f).apply {
        duration = 300
        interpolator = LinearInterpolator()
        start()
    }
    isExpanded = !isExpanded
}

Ou plus simplement (comme écrit @ Alex.F):

view.animate().setDuration(300).rotationBy(180f).start()
1
CoolMind

Code vérifié: (vous pouvez suivre ma solution)

imageView.setImageResource(R.drawable.ic_arrow_up);

boolean up = true;

if (!up) { 
    up = true; 
    imageView.startAnimation(animate(up)); 
} else { 
    up = false; 
    imageView.startAnimation(animate(up)); 
}

private Animation animate(boolean up) {
    Animation anim = AnimationUtils.loadAnimation(this, up ? R.anim.rotate_up : R.anim.rotate_down);
    anim.setInterpolator(new LinearInterpolator()); // for smooth animation
    return anim;
}

drawable/ic_arrow_up.xml

<vector xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:width="24dp"
        Android:height="24dp"
        Android:viewportWidth="24.0"
        Android:viewportHeight="24.0">
    <path
        Android:fillColor="#3d3d3d"
        Android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
</vector>

anim/rotation_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:fillAfter="true"
    Android:fillEnabled="true">
    <rotate
        Android:duration="200"
        Android:fromDegrees="-180"
        Android:pivotX="50%"
        Android:pivotY="50%"
        Android:toDegrees="0" />
</set>

anim/rotation_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:fillAfter="true"
    Android:fillEnabled="true">
    <rotate
        Android:duration="200"
        Android:fromDegrees="0"
        Android:pivotX="50%"
        Android:pivotY="50%"
        Android:toDegrees="180" />
</set>

J'ai utilisé ce code. Parce que cela sauvera l'état de l'animation:

Android:fillAfter="true"
Android:fillEnabled="true"
1
Ahamadullah Saikat