J'ai créé un fichier anim.xml comme ci-dessous pour agiter ImageView comme l'icône IOS trembler dans Android . Cependant, cela ne me donne pas le même résultat . Y at-il une meilleure idée?
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:duration="300"
Android:fromDegrees="-2"
Android:pivotX="50%"
Android:pivotY="50%"
Android:repeatCount="infinite"
Android:toDegrees="2" />
Essayez de régler Android:repeatMode="reverse"
. L’animation ci-dessous donne une impression très raisonnable sur mon Galaxy Nexus. Évidemment, vous pouvez ajuster les paramètres à votre guise.
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:duration="100"
Android:fromDegrees="-5"
Android:pivotX="50%"
Android:pivotY="50%"
Android:repeatCount="infinite"
Android:repeatMode="reverse"
Android:toDegrees="5" />
Vous pouvez essayer ceci:
shake.xml
<translate xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:fromXDelta="0"
Android:toXDelta="10"
Android:duration="1000"
Android:interpolator="@anim/cycle_7" />
cycle_7.xml
<cycleInterpolator xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:cycles="7" />
Belle animation de shake ;
res/anim/shake.xml
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
<translate Android:duration="150"
Android:fromXDelta="-10%"
Android:repeatCount="5"
Android:repeatMode="reverse"
Android:toXDelta="10%"/>
</set>
Comment l'utiliser
final Animation animShake = AnimationUtils.loadAnimation(this, R.anim.shake);
btn_done = (Button) findViewById(R.id.btn_act_confirm_done);
btn_done.startAnimation(animShake);
essayez d'utiliser celui-ci:
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
<rotate
Android:duration="70"
Android:fromDegrees="-5"
Android:pivotX="50%"
Android:pivotY="50%"
Android:repeatCount="5"
Android:repeatMode="reverse"
Android:interpolator="@Android:anim/linear_interpolator"
Android:toDegrees="5" />
<translate
Android:fromXDelta="-10"
Android:toXDelta="10"
Android:repeatCount="5"
Android:repeatMode="reverse"
Android:interpolator="@Android:anim/linear_interpolator"
Android:duration="70" />
</set>
J'ai créé un effet de shake sur Android et posté dans GitHub. Voyez si cela fonctionne mieux.
https://github.com/teoinke/ShakeAnimation
Code pertinent:
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:interpolator="@Android:anim/overshoot_interpolator"
Android:fillAfter="true">
<translate
Android:startOffset="100"
Android:fromXDelta="0%p"
Android:toXDelta="10%p"
Android:duration="50" />
<translate
Android:startOffset="150"
Android:fromXDelta="0%p"
Android:toXDelta="-25%p"
Android:duration="110" />
<translate
Android:startOffset="260"
Android:fromXDelta="0%p"
Android:toXDelta="25%p"
Android:duration="120" />
<translate
Android:startOffset="380"
Android:fromXDelta="0%p"
Android:toXDelta="-20%p"
Android:duration="130" />
<translate
Android:startOffset="510"
Android:fromXDelta="0%p"
Android:toXDelta="10%p"
Android:duration="140" />
</set>
Pour faire effet shake comme ça
Commencez par définir l'animation shake dans le dossier anim en tant que shake.xml.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
<rotate
Android:duration="70"
Android:fromDegrees="-5"
Android:interpolator="@Android:anim/linear_interpolator"
Android:pivotX="50%"
Android:pivotY="50%"
Android:repeatCount="5"
Android:repeatMode="reverse"
Android:toDegrees="5" />
<translate
Android:duration="70"
Android:fromXDelta="-10"
Android:interpolator="@Android:anim/linear_interpolator"
Android:repeatCount="5"
Android:repeatMode="reverse"
Android:toXDelta="10" />
</set>
Puis en code
if (TextUtils.isEmpty(phone.getText())
|| phone.getText().length() < 10)
{
//shake animation
phone.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.shake));
}
Celui-ci fonctionne plutôt bien (bien que pas tout à fait) comme un clone tremblant iOS:
final float FREQ = 3f;
final float DECAY = 2f;
// interpolator that goes 1 -> -1 -> 1 -> -1 in a sine wave pattern.
TimeInterpolator decayingSineWave = new TimeInterpolator() {
@Override
public float getInterpolation(float input) {
double raw = Math.sin(FREQ * input * 2 * Math.PI);
return (float)(raw * Math.exp(-input * DECAY));
}
};
shakeField.animate()
.xBy(-100)
.setInterpolator(decayingSineWave)
.setDuration(500)
.start();
J'ai créé une très bonne approximation de l'agitation iOS (lorsque vous appuyez longuement sur une icône pour supprimer l'application de l'écran d'accueil). Vous devez appliquer dans votre code, par programme, car il nécessite la génération de nombres aléatoires:
int dur1 = 70 + (int)(Math.random() * 30);
int dur2 = 70 + (int)(Math.random() * 30);
// Create an animation instance
Animation an = new RotateAnimation(-3, 3, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// Set the animation's parameters
an.setDuration(dur1); // duration in ms
an.setRepeatCount(-1); // -1 = infinite repeated
an.setRepeatMode(Animation.REVERSE);
an.setFillAfter(true); // keep rotation after animation
// Create an animation instance
Animation an2 = new TranslateAnimation(-TranslateAnimation.RELATIVE_TO_SELF,0.02f,
TranslateAnimation.RELATIVE_TO_SELF,0.02f,
-TranslateAnimation.RELATIVE_TO_SELF,0.02f,
TranslateAnimation.RELATIVE_TO_SELF,0.02f);
// Set the animation's parameters
an2.setDuration(dur2); // duration in ms
an2.setRepeatCount(-1); // -1 = infinite repeated
an2.setRepeatMode(Animation.REVERSE);
an2.setFillAfter(true); // keep rotation after animation
AnimationSet s = new AnimationSet(false);//false means don't share interpolators
s.addAnimation(an);
s.addAnimation(an2);
// Apply animation to image view
itemView.setAnimation(s);
Ce code a été conçu pour être appliqué à l'intérieur d'un gridview (getView), mais vous pouvez l'appliquer à n'importe quel affichage en modifiant la dernière ligne en:
yourViewName.setAnimations (s);
Pour les utilisateurs de Kotlin:
Commencez par créer un fichier de ressources d'animation appelé shake.xml. Faites un clic droit sur le dossier res dans Android Studio, puis cliquez sur Nouveau> Android Fichier de ressources> entrez secouez pour le nom du fichier et sélectionnez Animation pour la liste déroulante Type de ressource. Cliquez sur OK.
Inside shake.xml
collez ce qui suit:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
<translate Android:duration="200"
Android:fromXDelta="-5%"
Android:repeatCount="3"
Android:repeatMode="reverse"
Android:toXDelta="5%"/>
</set>
Maintenant, il suffit d'appeler sur une vue!
à partir d'un fragment:
myView.startAnimation(AnimationUtils.loadAnimation(view!!.context, R.anim.shake))
à partir d'une activité:
myView.startAnimation(AnimationUtils.loadAnimation(this, R.anim.shake))
(note - myView
est l'identifiant attribué à la vue que vous souhaitez animer)
Si vous souhaitez affiner l'animation, modifiez simplement les valeurs dans shake.xml
.
/**
*
* @param view view that will be animated
* @param duration for how long in ms will it shake
* @param offset start offset of the animation
* @return returns the same view with animation properties
*/
public static View makeMeShake(View view, int duration, int offset) {
Animation anim = new TranslateAnimation(-offset,offset,0,0);
anim.setDuration(duration);
anim.setRepeatMode(Animation.REVERSE);
anim.setRepeatCount(5);
view.startAnimation(anim);
return view;
}
utilisation:
TextView tv;
makeMeShake(tv,20,5); // it will shake quite fast
Me frappant la tête pendant plus de deux heures, je savais secouer et bouger une vue.
Malheureusement, la réponse acceptée ne fonctionnera pas en dehors de onCreateView de fragment.
Exemple si vous avez la méthode onClick et à l'intérieur de celle-ci. Vous avez une animation comme ci-dessous cela ne fonctionnera pas.
S'il vous plaît passer par le code.
DoneStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
register(view);
}
});
La méthode register a quelques contrôles comme le code ci-dessous
private void register(View view) {
String type = typedThings.getText.toString();
String km = Km_Now.getText().toString();
if (serviceType == null) {
animationServiceList = AnimationUtils.loadAnimation(getActivity(), R.anim.shake_wobble);
silverServiceButton.setAnimation(animationServiceList);
generalServiceButton.setAnimation(animationServiceList);
platinumServiceButton.setAnimation(animationServiceList);
animationServiceList.start();
} else if (km == null) {
animationEditText = AnimationUtils.loadAnimation(getActivity(), R.anim.shake_wobble);
Km_Now.setAnimation(animationEditText);
animationEditText.start();
}
L'appel animationServiceList.start (); ne sera jamais appelé,
SOLUTION: Utilisez PropertyAnimator comme ObjectAnimator.
L’animation par oscillation d’IOS n’est pas si simple. Essayez de changer les pivots x et y de façon aléatoire lors d’une rotation. Vous devez cependant modifier la valeur par programmation. Peut-être que vous pouvez aussi utiliser traduire une animation simultanément
D'autres réponses sont également correctes, mais elles sont un peu plus douces puisqu'elles utilisent un interpolateur qui produit des nombres lisses pour un retour en arrière.
public class WobblyView extends ImageView implements ValueAnimator.AnimatorUpdateListener {
private final ValueAnimator va = ValueAnimator.ofInt(-10, 10);
public WobblyView(Context context) {
this(context, null);
}
public WobblyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public WobblyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setAdjustViewBounds(true);
setImageResource(R.drawable.ic_logo);
va.setInterpolator(new AccelerateDecelerateInterpolator());
va.setRepeatMode(ValueAnimator.REVERSE);
va.setRepeatCount(ValueAnimator.INFINITE);
va.setDuration(1000);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
va.addUpdateListener(this);
va.start();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
va.removeUpdateListener(this);
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int heading = (int) animation.getAnimatedValue();
setRotation(heading);
}
}