animación de vista de temblor / oscilación en Android

82

Creé un archivo anim.xml como el siguiente para agitar la vista de imagen como el ícono de IOS temblando en Android. Sin embargo, no me proporciona el mismo resultado. ¿Hay alguna idea mejor?

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

Respuestas:

171

Intente configurar android:repeatMode="reverse". La siguiente animación ofrece una imitación muy razonable en mi Galaxy Nexus. Obviamente, puede ajustar los parámetros a su gusto.

<?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.
fuente
Soy nuevo en el desarrollo de Android, estoy usando Xamarin, ¿puede decirme cómo puedo aplicar esta animación a una imagen / botón en cualquier evento como hacer clic, etc.?
NK
@NK: Debería funcionar igual que en Java: cargue la animación por su ID de recurso y dígale a su vista que inicie la animación pasándola como parámetro. Debe ser algo como: view.StartAnimation(AnimationUtils.LoadAnimation(Resource.Animation.wobble)). Más detalles aquí y aquí .
MH.
3
¿Cómo podemos agregar el retraso entre sacudidas? por ejemplo, ¿mostrar agitación durante 500 ms y luego retrasar 1000 ms y luego repetir de nuevo?
Damir Mailybayev
74

Buena animación de batido ;

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>

Cómo usarlo

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

Cómo usarlo (versión más simple):

btn_done.startAnimation(AnimationUtils.loadAnimation(this,R.anim.shake));
Sam
fuente
3
android:duration="50"se ve mucho menos agitadas en mi opinión y se ve mejor muich
Ab
45

Puedes probar esto:

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" />

ciclo_7.xml

<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" 
                   android:cycles="7" />
adneal
fuente
10
Oye, supongo que cycle_7.xmlse puede sustituir por android:repeatCount="7"atributo en<translate .../>
Anup
28

intenta usar este:

<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>
Simón
fuente
19

Para hacer un efecto de agitación como este

ingrese la descripción de la imagen aquí

Primero defina la animación de agitación dentro de la carpeta anim como 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>

Entonces en código

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

Creé un efecto de vibración en Android y lo publiqué en GitHub. Vea si funciona mejor.

https://github.com/teoinke/ShakeAnimation

Código relevante:

<?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
fuente
1
Para mí, esta es la mejor respuesta, ya que se anima desde el centro y no compensa instantáneamente la imagen como algunas de las otras sugerencias. ¡Pro!
Jonathan Dunn
13

Este funciona bastante bien (aunque no perfectamente) como un clon de agitación de "PIN incorrecto" de 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
fuente
5
/**
 *
 * @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;
}

utilizar:

TextView tv;
makeMeShake(tv,20,5);    // it will shake quite fast
Sin viento
fuente
Funciona perfectamente y muy rápido.
George Vrynios
3

Creé una muy buena aproximación del temblor de iOS (cuando mantienes presionado un ícono para eliminar la aplicación de la pantalla de inicio). Debe aplicar dentro de su código, mediante programación, ya que requiere la generación de números aleatorios:

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

Este código fue diseñado para aplicarse dentro de la vista de cuadrícula de un adaptador (getView), pero puede aplicarlo a cualquier vista cambiando la última línea a:

yourViewName.setAnimations (s);

Adriano Moutinho
fuente
parece que no hace nada
user25
Tenga en cuenta que esto solo funcionará si itemViewaún no se agregó a ViewGroup. Si ya se agregó, utilícelo itemView.startAnimation(s)en su lugar.
Alex Semeniuk
2

Para usuarios de Kotlin:

Primero cree un archivo de recursos de animación llamado shake.xml . Haga clic con el botón derecho en la carpeta res en Android Studio, luego haga clic en Nuevo> Archivo de recursos de Android> ingrese agitar para el nombre del archivo y seleccione Animación para el menú desplegable Tipo de recurso. Haga clic en Aceptar.

En shake.xmlel interior pegue lo siguiente:

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

¡Ahora solo llámalo en una vista!

Desde dentro de un fragmento:

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

Desde dentro de una actividad:

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

(nota: myViewes el ID que se le da a la vista que desea animar)

Si desea ajustar la animación, simplemente modifique los valores en shake.xml.

Joe
fuente
startAnimationy anim(dentro R.anim.shake) hay referencias sin resolver, por favor, ¿pueden ayudarme? gracias
Maff
necesitas crear una carpeta anim en el directorio res @Maff
Aditya Patil
0

La animación de oscilación de IOS no es tan simple, intente cambiar el pivote xey aleatoriamente al rotar. Sin embargo, debe cambiar el valor programáticamente. Puede ser que también puedas usar la animación de traducción simultáneamente

wooram jung
fuente
0

Golpeándome la cabeza durante más de dos horas, supe cómo sacudir y mover una vista.

Desafortunadamente, la respuesta aceptada no funcionará aparte de onCreateView del fragmento.

Ejemplo si tiene el método onClick y dentro de él. Tienes una animación como la de abajo, no funcionará.

Por favor revise el código.

    DoneStart.setOnClickListener(new OnClickListener() {

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

        }
    });

El método de registro tiene algunas verificaciones como el siguiente código

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

La llamada animationServiceList.start (); nunca será llamado,

SOLUCIÓN: Utilice PropertyAnimator como ObjectAnimator.

EngineSense
fuente
0

Otras respuestas también son correctas, pero esto es un poco más suave que ellas, ya que utiliza un interpolador que produce números suaves para el movimiento hacia adelante y hacia atrás.

    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
fuente