Shaking / Wobble View Animation in Android

82

Ich habe eine anim.xml-Datei wie die folgende erstellt, um die Bildansicht wie das IOS-Symbol in Android zu erschüttern. Es liefert mir jedoch nicht das gleiche Ergebnis. Gibt es eine bessere Idee?

<?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" />
Winston
quelle

Antworten:

171

Versuchen Sie die Einstellung android:repeatMode="reverse". Die folgende Animation gibt eine sehr vernünftige Nachahmung auf meinem Galaxy Nexus. Natürlich können Sie die Parameter nach Ihren Wünschen einstellen.

<?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" />
MH.
quelle
Ich bin neu in der Android-Entwicklung, ich verwende Xamarin. Können Sie mir bitte sagen, wie ich diese Animation auf ein Bild / eine Schaltfläche bei einem Ereignis wie Klick usw. anwenden kann?
NK
@NK: Es sollte genauso funktionieren wie in Java: Laden Sie die Animation anhand ihrer Ressourcen-ID und teilen Sie Ihrer Ansicht mit, dass die Animation gestartet werden soll, indem Sie sie als Parameter übergeben. Sollte ungefähr so ​​aussehen : view.StartAnimation(AnimationUtils.LoadAnimation(Resource.Animation.wobble)). Weitere Details hier und hier .
MH.
3
Wie können wir die Verzögerung zwischen dem Schütteln hinzufügen? Zum Beispiel Shake für 500 ms zeigen, dann Verzögerung für 1000 ms, dann noch einmal wiederholen?
Damir Mailybayev
74

Schöne Shake-Animation ;

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>

Wie man es benutzt

final Animation animShake = AnimationUtils.loadAnimation(this, R.anim.shake);
btn_done = (Button) findViewById(R.id.btn_act_confirm_done); 
btn_done.startAnimation(animShake);

Wie man es benutzt (einfachere Version):

btn_done.startAnimation(AnimationUtils.loadAnimation(this,R.anim.shake));
Sam
quelle
3
android:duration="50"sieht meiner Meinung nach viel weniger abgehackt aus und sieht viel besser aus
Ali Bdeir
45

Sie könnten dies versuchen:

schütteln.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" />
adneal
quelle
10
Hey, ich denke, cycle_7.xmlkann durch android:repeatCount="7"Attribut in ersetzt werden<translate .../>
Anup
28

versuche diesen zu benutzen:

<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>
Simon
quelle
19

So einen Shake-Effekt erzielen

Geben Sie hier die Bildbeschreibung ein

Definieren Sie zuerst die Shake-Animation im Animationsordner alsake.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>

Dann im Code

if (TextUtils.isEmpty(phone.getText())
 || phone.getText().length() < 10)
    {
     //shake animation
    phone.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.shake));
     }
Hitesh Sahu
quelle
14

Ich habe einen Shake-Effekt auf Android erstellt und in GitHub gepostet. Sehen Sie, ob es besser funktioniert.

https://github.com/teoinke/ShakeAnimation

Relevanter Code:

<?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>
Teo Inke
quelle
1
Für mich ist dies die beste Antwort, da es von der Mitte aus animiert und das Bild nicht sofort wie einige der anderen Vorschläge versetzt. Profi!
Jonathan Dunn
13

Dieser funktioniert ziemlich gut (wenn auch nicht perfekt) als iOS-Shake-Klon mit "falscher PIN":

    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();
lincolnq
quelle
6
/**
 *
 * @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;
}

verwenden:

TextView tv;
makeMeShake(tv,20,5);    // it will shake quite fast
Windstill
quelle
Funktioniert perfekt und sehr schnell.
George Vrynios
3

Ich habe eine sehr gute Annäherung an das Verwackeln von iOS erstellt (wenn Sie lange auf ein Symbol drücken, um die App vom Homescreen zu entfernen). Sie müssen programmgesteuert in Ihrem Code anwenden, da dafür Zufallszahlen generiert werden müssen:

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

Dieser Code wurde entworfen, um in der Rasteransicht eines Adapters (getView) angewendet zu werden. Sie können ihn jedoch auf jede Ansicht anwenden, indem Sie die letzte Zeile in Folgendes ändern:

yourViewName.setAnimations (s);

Adriano Moutinho
quelle
Anscheinend tut es nichts
user25
Bitte beachten Sie, dass dies nur funktioniert, wenn itemViewes noch nicht zu ViewGroup hinzugefügt wurde. Wenn es bereits hinzugefügt wurde, verwenden Sie itemView.startAnimation(s)stattdessen.
Alex Semeniuk
2

Für Kotlin-Benutzer:

Erstellen Sie zunächst eine Animationsressourcendatei mit dem Namenakes.xml . Klicken Sie mit der rechten Maustaste auf den Ordner res in Android Studio, klicken Sie dann auf Neu> Android-Ressourcendatei> geben Sie Shake als Dateinamen ein und wählen Sie Animation Dropdown-Liste für Ressourcentyp aus. OK klicken.

shake.xmlFügen Sie im Inneren Folgendes ein:

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

Nennen Sie es jetzt einfach auf eine Ansicht!

Aus einem Fragment heraus:

myView.startAnimation(AnimationUtils.loadAnimation(view!!.context, R.anim.shake))

Aus einer Aktivität heraus:

myView.startAnimation(AnimationUtils.loadAnimation(this, R.anim.shake))

(Hinweis - myViewist die ID der Ansicht, die Sie animieren möchten.)

Wenn Sie die Animation optimieren möchten, ändern Sie einfach die Werte in shake.xml.

Joe
quelle
startAnimationund anim(innerhalb R.anim.shake) sind beide ungelöste Referenzen, können Sie bitte helfen? danke
Maff
Sie müssen einen Animationsordner im res-Verzeichnis @Maff
Aditya Patil
0

IOS Wobble-Animation ist nicht so einfach. Versuchen Sie, Pivot x und y beim Drehen zufällig zu ändern. Sie sollten den Wert jedoch programmgesteuert ändern. Möglicherweise können Sie die Übersetzungsanimation auch gleichzeitig verwenden

wooram jung
quelle
0

Ich schlug mehr als zwei Stunden lang mit dem Kopf und wusste, wie man einen Blick schüttelt und wackelt.

Leider funktioniert die akzeptierte Antwort außer onCreateView des Fragments nicht.

Beispiel, wenn Sie eine onClick-Methode haben und darin enthalten sind. Sie haben Animation wie unten, es wird nicht funktionieren.

Bitte gehen Sie den Code durch.

    DoneStart.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View view) {
           register(view);

        }
    });

Die Registermethode hat einige Überprüfungen wie den folgenden Code

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

Der Aufruf animationServiceList.start (); wird niemals genannt werden,

LÖSUNG: Verwenden Sie PropertyAnimator wie ObjectAnimator.

EngineSense
quelle
0

Andere Antworten sind ebenfalls korrekt, aber dies ist etwas flüssiger als sie, da ein Interpolator glatte Zahlen für eine Hin- und Herbewegung erzeugt

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