potrząsanie / chybotanie animacji widoku w systemie Android

84

Utworzyłem plik anim.xml, taki jak poniżej, aby potrząsać widokiem obrazu, takim jak ikona IOS w systemie Android. Jednak nie daje mi to takiego samego rezultatu. Czy jest lepszy pomysł?

<?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
źródło

Odpowiedzi:

172

Spróbuj ustawić android:repeatMode="reverse". Poniższa animacja daje bardzo rozsądną imitację na moim Galaxy Nexusie. Oczywiście możesz dostosować parametry do własnych upodobań.

<?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.
źródło
Jestem nowy w programowaniu na Androida, używam Xamarin, czy możesz mi powiedzieć, jak mogę zastosować tę animację do obrazu / przycisku w dowolnym zdarzeniu, takim jak kliknięcie itp.
NK
@NK: Powinno działać tak samo jak w Javie: załaduj animację za pomocą identyfikatora zasobu i powiedz swojemu widokowi, aby rozpoczął animację, przekazując ją jako parametr. Powinien wyglądać mniej więcej tak: view.StartAnimation(AnimationUtils.LoadAnimation(Resource.Animation.wobble)). Więcej szczegółów tutaj i tutaj .
MH.
3
Jak możemy dodać opóźnienie między wstrząsami. na przykład pokaż wstrząsnąć przez 500 ms, a następnie opóźnij przez 1000 ms, a następnie powtórz ponownie?
Damir Mailybayev
76

Ładna animacja potrząsania ;

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>

Jak tego użyć

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

Jak z niego korzystać (prostsza wersja):

btn_done.startAnimation(AnimationUtils.loadAnimation(this,R.anim.shake));
Sam
źródło
3
android:duration="50"wygląda na mniej wzburzony moim zdaniem i wygląda muich lepiej
Ali Bdeir
45

Możesz spróbować tego:

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" />
adneal
źródło
10
hej, myślę, że cycle_7.xmlmożna go zastąpić android:repeatCount="7"atrybutem<translate .../>
Anup
28

spróbuj użyć tego:

<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>
Szymon
źródło
19

Aby uzyskać taki efekt wstrząsu

wprowadź opis obrazu tutaj

Najpierw zdefiniuj animację potrząśnięcia w folderze anim jako 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>

Następnie w kodzie

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

Stworzyłem efekt wstrząsu na Androida i opublikowałem na GitHubie. Sprawdź, czy działa lepiej.

https://github.com/teoinke/ShakeAnimation

Odpowiedni kod:

<?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
źródło
1
Dla mnie jest to najlepsza odpowiedź, ponieważ animuje od środka i nie wyrównuje natychmiast obrazu, tak jak niektóre inne sugestie. Zawodowiec!
Jonathan Dunn,
13

Ten działa całkiem nieźle (choć nie idealnie) jako klon do wstrząsania „nieprawidłowym kodem PIN” 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();
Lincolnq
źródło
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;
}

posługiwać się:

TextView tv;
makeMeShake(tv,20,5);    // it will shake quite fast
Bezwietrznie
źródło
Działa doskonale i bardzo szybko.
George Vrynios
3

Stworzyłem bardzo dobre przybliżenie drgań iOS (gdy długo naciskasz ikonę, aby usunąć aplikację z ekranu głównego). Musisz aplikować wewnątrz swojego kodu, programowo, ponieważ wymaga to generowania liczb losowych:

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

Ten kod został zaprojektowany do zastosowania w widoku siatki adaptera (getView), ale można go zastosować do dowolnego widoku, zmieniając ostatni wiersz na:

yourViewName.setAnimations (s);

Adriano Moutinho
źródło
wydaje się, że nic nie robi
użytkownik25
Pamiętaj, że zadziała to tylko wtedy, gdy itemViewnie został jeszcze dodany do ViewGroup. Jeśli został już dodany, użyj itemView.startAnimation(s)zamiast tego.
Alex Semeniuk
2

Dla użytkowników Kotlin:

Najpierw utwórz plik zasobów animacji o nazwie shake.xml . Kliknij prawym przyciskiem myszy folder res w Android Studio, a następnie kliknij Nowy> Plik zasobów systemu Android> wprowadź wstrząsnąć jako nazwę pliku i wybierz Animacja dla rozwijanego typu zasobu. Kliknij OK.

Wewnątrz shake.xmlwklej następujące elementy:

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

Teraz po prostu wywołaj widok!

Z fragmentu:

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

Z poziomu działania:

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

(Uwaga - myView to identyfikator nadany widokowi, który chcesz animować)

Jeśli chcesz dopracować animację, po prostu zmodyfikuj wartości w shake.xml.

Joe
źródło
startAnimationi anim(w obrębie R.anim.shake) są nierozwiązanymi odwołaniami, czy możesz pomóc? dzięki
Maff
musisz utworzyć folder anim w katalogu res @Maff
Aditya Patil
0

Animacja chybotania w iOS nie jest taka prosta, próba losowej zmiany osi xiy podczas obracania. Jednak powinieneś zmienić tę wartość programowo. Być może możesz jednocześnie użyć animacji tłumaczenia

wooram jung
źródło
0

Uderzając głową przez ponad dwie godziny, wiedziałem, jak potrząsać i chybotać widok.

Niestety zaakceptowana odpowiedź nie będzie działać poza onCreateView fragmentu.

Przykład, jeśli masz metodę onClick i wewnątrz niej. Masz animację jak poniżej, ale nie zadziała.

Proszę przejść przez kod.

    DoneStart.setOnClickListener(new OnClickListener() {

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

        }
    });

Metoda rejestracji ma pewne kontrole, takie jak poniższy kod

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

Call animationServiceList.start (); nigdy nie zostanie wezwany,

ROZWIĄZANIE: Użyj PropertyAnimator jak ObjectAnimator.

EngineSense
źródło
0

Inne odpowiedzi również są poprawne, ale jest to nieco płynniejsze niż one, ponieważ używa interpolatora, który generuje płynne liczby dla ruchu w przód iw tył

    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
źródło