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?
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.
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);
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);
}
});
}
}
Vous pouvez utiliser setFillAfter
si vous souhaitez conserver l'état de votre animation.
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()
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"