oreo - juego android 7.0 samsung
La animaciĆ³n de Android no se repite (23)
Intento hacer animaciones simples que se repitan varias veces (o infinitamente).
Parece que android:repeatCount
no funciona!
Aquí está mi recurso de animación de /res/anim/first_animation.xml
:
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:repeatCount="infinite"
>
<scale
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="500"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="1.2"
android:toYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false" />
<scale
android:interpolator="@android:anim/accelerate_interpolator"
android:startOffset="500"
android:duration="500"
android:fromXScale="1.2"
android:fromYScale="1.2"
android:toXScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false" />
</set>
En primer lugar, debe escalar la imagen del tamaño de 1.0 a 1.2 en 500 ms.
Y luego escalarlo de nuevo a 1.0 en 500 ms.
Así es como lo estoy usando:
Animation firstAnimation = AnimationUtils.loadAnimation(this, R.anim.first_animation);
imgView.startAnimation(firstAnimation);
Hace un ciclo y luego termina.
Se amplía, luego se reduce y luego se detiene.
¿Cómo puedo hacer que esto funcione según lo previsto?
Acabo de enterarme de este problema mientras trabajaba en una aplicación compatible con versiones anteriores. ¡muy frustrante! Terminé codificando una buena clase de solución que se puede llamar desde onCreate y que iniciará cualquier recurso de animación en un ciclo indefinido.
la clase, AnimationLooper, está disponible aquí: https://gist.github.com/2018678
Agregue la siguiente clase a su proyecto:
import android.view.View;
import android.view.animation.Animation;
public class AnimationRepeater implements Animation.AnimationListener
{
private View view;
private Animation animation;
private int count;
public AnimationRepeater(View view, Animation animation)
{
this.view = view;
this.animation = animation;
this.count = -1;
}
public AnimationRepeater(View view, Animation animation, int count)
{
this.view = view;
this.animation = animation;
this.count = count;
}
public void start()
{
this.view.startAnimation(this.animation);
this.animation.setAnimationListener(this);
}
@Override
public void onAnimationStart(Animation animation) { }
@Override
public void onAnimationEnd(Animation animation)
{
if (this.count == -1)
this.view.startAnimation(animation);
else
{
if (count - 1 >= 0)
{
this.animation.start();
count --;
}
}
}
@Override
public void onAnimationRepeat(Animation animation) { }
}
Para un bucle infinito de su vista, haga lo siguiente:
Animation a = AnimationUtils(Context, R.anim.animation);
new AnimationRepeater(View, a).start();
Si desea repetir la animación solo N veces, haga lo siguiente:
Animation a = AnimationUtils(Context, R.anim.animation);
new AnimationRepeater(View, a, int N).start();
N significa número de repeticiones.
Con Android SDK versión 4.0.3:
En los elementos de animación dados:
android: repeatCount = "- 1"
lo hace una animación infinita.
Debes incluir el atributo
android:repeatCount="infinite"
Pero en tu animación de "escala" no está en "establecer"
Descubrí que la etiqueta <set> tiene una implementación incorrecta en la clase AnimationSet .
No puede tratar correctamente con repeatCount .
Lo que podemos hacer es establecer repeatCount directamente en la etiqueta <scale> .
Este recurso XML está funcionando bien:
<?xml version="1.0" encoding="utf-8"?>
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:duration="200"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="1.05"
android:toYScale="1.05"
android:pivotX="50%"
android:pivotY="50%"
android:repeatMode="reverse"
android:fillAfter="false"
android:repeatCount="24"
/>
Lamentablemente, esto se limita a una sola animación a la vez.
No podemos definir una secuencia de animaciones de esta manera ...
Después de investigar a través de las respuestas de internet, encontré una solución que funciona perfectamente para mí. (Y sí, el repeatCount y repeatMode es extremadamente defectuoso cuando se usa junto con animationSet).
anim_rotate_fade.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:ordering="together" >
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:repeatCount="1"
android:valueTo="360"
android:valueType="floatType" />
<objectAnimator
android:duration="3000"
android:propertyName="alpha"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="0.0"
android:valueTo="0.3"
android:valueType="floatType" />
<objectAnimator
android:duration="3000"
android:propertyName="y"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="380"
android:valueTo="430"
android:valueType="floatType" />
</set>
En actividad: (Resuélvelo introduciendo un ligero retraso después de que finalice la animación).
ImageView starlightImageView = new ImageView(this);
starlightImageView.setImageResource(R.drawable.starlight);
final AnimatorSet animate = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.anim.anim_rotate_fade);
AnimatorListenerAdapter animatorListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
new Handler().postDelayed(new Runnable() {
@Override public void run() {
animate.start();
}
}, 1000);
}
};
animate.setTarget(starlightImageView);
animate.addListener(animatorListener);
Hay muchas clases en las que te gustaría investigar, pero actualmente estoy usando ObjectAnimator, que es muy flexible. No recomendaría usar Animation o AnimationUtils:
- Animación
- AnimationUtils
- Animador
- AnimatorInflater
- AnimatorListener
- AnimatorListenerAdapter
Es necesario escuchar la finalización de la primera animación y luego reiniciar la animación en la llamada de retorno de OnStopAnimation, probar en este link
Hago la mayor parte de mis cosas programáticamente y puedo llegar tarde o ser ineficaz en este caso pero esto, pero he completado el objetivo de repetir el conjunto de animaciones (incluso tengo 2 conjuntos de animación alternativos). Todo lo que este código hace es simplemente desvanecerse en una imagen, pausar, luego fundirse, fundirse en otra imagen, pausar, fundirse y traer la primera (enjuague y repetición). Primero definí mis Imageviews:
final ImageView purple = (ImageView)findViewById(R.id.purp);
final ImageView yellow = (ImageView)findViewById(R.id.yell);
purple.setVisibility(View.INVISIBLE);
yellow.setVisibility(View.INVISIBLE);
Luego hice dos temporizadores, temporizadores de tareas y manejadores para tratar cuándo comenzar y detener cada animación:
Timer p = new Timer();
TimerTask pu = new TimerTask() {
public void run() {
handler1.post(new Runnable() {
public void run()
{
fadein(purple);
}
});
}};
p.schedule(pu, 6000, 12000);
final Handler handler2 = new Handler();
Timer y = new Timer();
TimerTask ye = new TimerTask() {
public void run() {
handler2.post(new Runnable() {
public void run()
{
fadein(yellow);
}
});
}};
y.schedule(ye, 0, 12000);
Finalmente, en lugar de crear conjuntos de animación agregando animaciones, solo hago una animación de los oyentes para determinar cuándo comenzar cada animación:
public void fadein (final ImageView image)
{
Animation anim = new AlphaAnimation(0, 1);
anim.setDuration(2000);
image.startAnimation(anim);
anim.setAnimationListener(new AnimationListener() {
public void onAnimationEnd(Animation animation)
{
image.clearAnimation();
image.invalidate();
pause(image);
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
});
}
public void pause (final ImageView image)
{
Animation anim = new AlphaAnimation(1, 1);
anim.setDuration(2000);
image.startAnimation(anim);
anim.setAnimationListener(new AnimationListener() {
public void onAnimationEnd(Animation animation)
{
image.clearAnimation();
image.invalidate();
fadeout(image);
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
});
}
public void fadeout (final ImageView image)
{
Animation anim = new AlphaAnimation(1,0);
anim.setDuration(2000);
image.startAnimation(anim);
anim.setAnimationListener(new AnimationListener() {
public void onAnimationEnd(Animation animation)
{
image.clearAnimation();
image.invalidate();
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
});
}
La eliminación e invalidación donde solo los intentos anteriores y hacer que esto funcione bien. No sé si se requieren o no.
Espero que esto ayude a alguien.
Ryan
He resuelto este problema. Esta es mi versión de la corrección:
public class HelloAndroidActivity extends Activity {
private static String TAG = "animTest";
private Animation scaleAnimation;
private int currentCover = 0;
private List<ImageView> imageViews = new ArrayList<ImageView>(3);
private Button btn;
private ImageView img;
/**
* Called when the activity is first created.
* @param savedInstanceState If the activity is being re-initialized after
* previously being shut down then this Bundle contains the data it most
* recently supplied in onSaveInstanceState(Bundle). <b>Note: Otherwise it is null.</b>
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate");
setContentView(R.layout.test);
img = (ImageView)findViewById(R.id.testpict);
imageViews.add(img);
img = (ImageView)findViewById(R.id.testpictTwo);
imageViews.add(img);
img = (ImageView)findViewById(R.id.testpict3);
imageViews.add(img);
scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.photo_scale);
scaleAnimation.setAnimationListener(new CyclicAnimationListener());
btn = (Button)findViewById(R.id.startBtn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
imageViews.get(0).startAnimation(scaleAnimation);
}
});
}
private class CyclicAnimationListener implements AnimationListener{
@Override
public void onAnimationEnd(Animation animation) {
currentCover += 1;
if(currentCover >= imageViews.size()){
currentCover = 0;
}
img = imageViews.get(currentCover);
scaleAnimation = AnimationUtils.loadAnimation(HelloAndroidActivity.this, R.anim.photo_scale);
scaleAnimation.setAnimationListener(new CyclicAnimationListener());
img.startAnimation(scaleAnimation);
}
@Override
public void onAnimationRepeat(Animation animation) {
Log.d("Animation", "Repeat");
}
@Override
public void onAnimationStart(Animation animation) {
}
}
}
Intente agregar el código a una secuencia de bucles o una instrucción while / for
Me enfrenté al mismo problema, pero no quería hacer ningún ajuste temporal en Java debido al hecho de que el hilo de la interfaz de usuario puede estar muy ocupado a veces. La bandera INFINITE no funciona para la etiqueta establecida. Así que resolví el problema con un pequeño fragmento de código:
mAnimation = (AnimationSet) AnimationUtils.loadAnimation(myContext, R.anim.blink);
mIcon.startAnimation(mAnimation);
mAnimation.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation animation) {}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {
mIcon.startAnimation(mAnimation);
}
});
con el siguiente XML:
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="0.9"
android:startOffset="1000"
android:toAlpha="0.0" />
Donde mIcon es un ImageView de mi diseño.
Ninguna de las soluciones anteriores funcionó en mi caso. La solución de Danuofr funcionaba para el conjunto de animación, pero cuando estaba haciendo pruebas unitarias, mis pruebas solían atascarse en este ciclo infinito. Finalmente, específicamente para mi caso, necesitaba repetir esta animación una cantidad específica de veces. Entonces, manualmente agregué copias de mi animación en anim_rot.xml de una manera en cascada, agregando el valor de compensación . Sé que es malo y no funcionará para muchos, pero fue la única solución para mi caso.
anim_rot.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="2000"
android:fromDegrees="20"
android:pivotX="29%"
android:pivotY="50%"
android:toDegrees="-20" />
<rotate
android:duration="2000"
android:fromDegrees="-20"
android:pivotX="29%"
android:pivotY="53%"
android:startOffset="2000"
android:toDegrees="20" />
<rotate
android:startOffset="4000"
android:duration="2000"
android:fromDegrees="20"
android:pivotX="29%"
android:pivotY="56%"
android:toDegrees="-20" />
<rotate
android:duration="2000"
android:fromDegrees="-20"
android:pivotX="29%"
android:pivotY="59%"
android:startOffset="6000"
android:toDegrees="20" />
<rotate
android:startOffset="8000"
android:duration="2000"
android:fromDegrees="20"
android:pivotX="29%"
android:pivotY="62%"
android:toDegrees="-20" />
<rotate
android:duration="2000"
android:fromDegrees="-20"
android:pivotX="29%"
android:pivotY="65%"
android:startOffset="10000"
android:toDegrees="20" />
</set>
Hice esto para repetir la animación 3 veces. Puede agregar más copias para repetir las horas específicas agregando valores de compensación.
Para obtener una animación repetitiva utilicé el oyente de animación y llamé a la animación nuevamente cuando finalizó. Esto hace que una retícula de cámara se enfoque como animación con corchetes.
Aquí está el diseño de animación xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1.0"
android:toXScale=".7"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toYScale=".7"
android:duration="1000"/>
<scale
android:duration="1000"
android:fromXScale=".7"
android:toXScale="1.0"
android:fromYScale=".7"
android:pivotX="50%"
android:pivotY="50%"
android:toYScale="1.0"
android:startOffset="1000"/>
</set>
Aquí está el código java
public void startAnimation() {
View brackets = findViewById(R.id.brackets);
brackets.setVisibility(View.VISIBLE);
Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
anim.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationEnd(Animation arg0) {
Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
anim.setAnimationListener(this);
brackets.startAnimation(anim);
}
@Override
public void onAnimationRepeat(Animation arg0) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationStart(Animation arg0) {
// TODO Auto-generated method stub
}
});
brackets.startAnimation(anim);
}
Poco retoque a la respuesta de @Danufr para evitar que los recursos se carguen nuevamente.
operator = (ImageView) findViewById(R.id.operator_loading);
final Animation ani = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.finding_operator);
ani.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
operator.startAnimation(ani);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
operator.setAnimation(ani);
Resolví este problema usando hilo.
Button btn = (Button) findViewById(R.id.buttonpush);
final TextView textview = (TextView) findViewById(R.id.hello);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
textview.setText("...................");
final Animation animationtest = AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_in_left);
animationtest.setDuration(1000);
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
handler.postDelayed(this, 1500);
textview.startAnimation(animationtest);
}
};
handler.postDelayed(runnable, 500); // start
handler.removeCallbacks(runnable); //STOP Timer
}
});
Resolví este problema usando reverse antes en mi proyecto.
<scale android:interpolator="@android:anim/decelerate_interpolator" android:duration="500" android:fromXScale="1.0" android:fromYScale="1.0" android:toXScale="1.2" android:toYScale="1.2" android:pivotX="50%" android:pivotY="50%" android:repeatMode="reverse" android:repeatCount="infinite" />
También estaba enfrentando el mismo problema ... incluí Android: repeatCount = "infinito" en el archivo XMl ... ahora está funcionando bien ...
<translate
android:fromXDelta="0"
android:toXDelta="80"
android:duration="1000"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"/>
Tengo esto para ir ... estaba tratando de obtener una vista para rotar en un círculo continuamente.
anterior estaba usando rotation.setRepeatMode (-1) pero eso no funcionó. cambió a setrepeatcount y funciona. Esto es en Jelly Bean 4.2.2
ObjectAnimator rotation = ObjectAnimator.ofFloat(myview,
"rotation", 360).setDuration(2000);
rotation.setRepeatMode(-1);
rotation.setRepeatCount(Animation.INFINITE);
rotation.start();
Traté de usar el código de Daniel para mostrar la animación el número exacto de veces y tuve un problema: la animación se mostraba aproximadamente n / 2 veces, cuando se esperaba n veces.
Así que modifiqué el código de Daniel:
//...
@Override
public void onAnimationEnd(Animation arg0) {
mCurrentCount++;
if (mCurrentCount < REPEAT_COUNT) {
Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
anim.setAnimationListener(this);
brackets.post(new Runnable() {
@Override
public void run() {
brackets.startAnimation(anim);
}
}
}
}
//...
Usando la variante, que se muestra arriba, la animación se muestra, por ejemplo, REPEAT_COUNT veces, porque el método View.post () da la posibilidad de iniciar una nueva animación después de finalizar todas las acciones relacionadas con la animación anterior.
funciona bien
GifDrawable gifDrawable = (GifDrawable) gifImageView.getDrawable();
gifDrawable.setLoopCount(0);
puedes probar este código En tu código simplemente agrega,
firstAnimation.setRepeatCount(5);
Esto repetirá la animación por un tiempo definido
firstAnimation.setRepeatCount(Animation.INFINITE);
firstAnimation.setRepeatMode(Animation.INFINITE);
Esto repetirá la animación indefinidamente.
tienes que agregar solo una línea en tu código xml que sugerí a continuación.
<scale
android:duration="500"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="1.2"
android:toYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite" // just add this one line
android:fillAfter="false"
/>
</set>
Actualización: en septiembre de 2011, un ingeniero de Android solucionó este problema en su mayor parte. Los atributos que se ignoraron en XML ahora funcionan, con la excepción de repeatCount
y fillEnabled
que aún se ignoran (a propósito por algún motivo). Esto significa que todavía no es fácil repetir un AnimationSet
desafortunadamente.
Para obtener detalles, consulte la información general en los documentos actualizados (explica qué atributos se ignoran, cuáles funcionan y cuáles se pasan a los niños). Y para una comprensión más profunda de lo que fillAfter
, fillBefore
y fillEnabled
realmente hacen, consulte la fillEnabled
del ingeniero (Chet Haase) al respecto here .
Respuesta original
Para ampliar las respuestas de Pavel y otros: es cierto que la etiqueta <set>
es ridículamente defectuosa. No puede tratar correctamente con repeatCount
y una serie de otros atributos.
Pasé unas pocas horas averiguando qué puede y qué no puedo solucionar y he enviado un informe / problema de error aquí: Issue 17662
En resumen (esto se refiere a los conjuntos de AnimationSet
):
setRepeatCount () / android: repeatCount
Este atributo (así como repeatMode) no funciona en código o XML. Esto hace que repetir un conjunto completo de animaciones sea difícil.
setDuration () / android: duración
Configurar esto en un conjunto de animación en el código WORKS (anula todas las duraciones de las animaciones secundarias), pero no cuando se incluye en la etiqueta en XML
setFillAfter () / android: fillAfter
Esto funciona tanto en código como en XML para la etiqueta. Extrañamente, he conseguido que también funcione sin la necesidad de configurar fillEnabled en true.
setFillBefore () / android: fillBefore
Parece que no tiene efecto / se ignora tanto en código como en XML
setFillEnabled () / android: fillEnabled
Parece que no tiene efecto / ignorado tanto en código como en XML. Todavía puedo obtener fillAfter para trabajar incluso sin incluir fillEnabled o estableciendo fillEnabled en falso.
setStartOffset () / android: startOffset
Esto solo funciona en código y no en XML.