skip to Main Content

I want to an animation that infinitely moves images up and down. However when I run my code, the animation only happens once. This is the animation xml:

<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:repeatCount="3"
    android:repeatMode="restart">
   <!-- move down -->
   <translate
       android:fromYDelta="0%"
       android:toYDelta="50%"
       android:duration="1500"
       android:fillAfter="true"/>

   <!-- move up -->
   <translate
       android:fromYDelta="0%"
       android:startOffset="1500"
       android:toYDelta="-50%"
       android:duration="1500"
       android:fillAfter="true"/>

   <!-- continue to move up -->
   <translate
       android:fromYDelta="0%"
       android:startOffset="3000"
       android:toYDelta="-20%"
       android:duration="600"
       android:fillAfter="true"/>

   <!-- down to original pos -->
   <translate
       android:fromYDelta="0%"
       android:startOffset="3600"
       android:toYDelta="20%"
       android:duration="600"
       android:fillAfter="true"/>

</set>


This is my java code:

public class MainActivity extends AppCompatActivity {

    Animation move1, move2, move3, move4, move5;
    Button login;
    ImageView bar1, bar2, bar3, bar4, bar5;
    int delay1 = 500;
    int delay2 = 1560;
    int delay3 = 2300;
    int delay4 = 3065;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);

        login = findViewById(R.id.btLogin);
        bar1 =  findViewById(R.id.ivBar1);
        bar2 =  findViewById(R.id.ivBar2);
        bar3 =  findViewById(R.id.ivBar3);
        bar4 =  findViewById(R.id.ivBar4);
        bar5 =  findViewById(R.id.ivBar5);

        move1= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move);
        move2= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move);
        move3= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move);
        move4= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move);
        move5= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.move);

        bar1.startAnimation(move1);

        Handler handler = new Handler();
        handler.postDelayed(() -> bar2.startAnimation(move2), delay1);
        handler.postDelayed(() -> bar3.startAnimation(move3), delay2);
        handler.postDelayed(() -> bar4.startAnimation(move4), delay3);
        handler.postDelayed(() -> bar5.startAnimation(move5), delay4);


        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });
    }
}

Why doesn’t it repeat infinelty? Does it have something to do with the fill-after attribute in xml? Help would be greatly appreciated, its for a class project.

2

Answers


  1. Remove android:fillAfter="true" from your animation XML and set android:repeatCount="infinite" in the parent <set> tag instead of repeatCount="3". The fillAfter was keeping each animation in its final state, preventing proper looping.

    <?xml version="1.0" encoding="utf-8"?>
    <set
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:interpolator="@android:anim/linear_interpolator"
       android:repeatCount="infinite"
       android:repeatMode="restart">
      <!-- move down -->
      <translate
          android:fromYDelta="0%"
          android:toYDelta="50%"
          android:duration="1500"/>
    
      <!-- move up -->
      <translate
          android:fromYDelta="50%"
          android:startOffset="1500"
          android:toYDelta="-50%"
          android:duration="1500"/>
    
      <!-- continue to move up -->
      <translate
          android:fromYDelta="-50%"
          android:startOffset="3000"
          android:toYDelta="-20%"
          android:duration="600"/>
    
      <!-- down to original pos -->
      <translate
          android:fromYDelta="-20%"
          android:startOffset="3600"
          android:toYDelta="0%"
          android:duration="600"/>
    
    </set>
    

    That’s all you need to make it loop infinitely.

    Login or Signup to reply.
  2. You should change countRepeat attribute to value infinite. And move it into the first translate tag.

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- move down -->
    <translate
        android:fromYDelta="0%"
        android:toYDelta="50%"
        android:duration="1500"
        android:fillAfter="true"
        android:repeatCount="infinite"
        android:interpolator="@android:anim/linear_interpolator"/>
    
    <!-- move up -->
    <translate
        android:fromYDelta="0%"
        android:startOffset="1500"
        android:toYDelta="-50%"
        android:duration="1500"
        android:fillAfter="true"/>
    
    <!-- continue to move up -->
    <translate
        android:fromYDelta="0%"
        android:startOffset="3000"
        android:toYDelta="-20%"
        android:duration="600"
        android:fillAfter="true"/>
    
    <!-- down to original pos -->
    <translate
        android:fromYDelta="0%"
        android:startOffset="3600"
        android:toYDelta="20%"
        android:duration="600"
        android:fillAfter="true"/>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search