1

I'm trying to make a simple slideshow that fades out and fades in a few images without a button click. I had found a few examples to assist me, but I am having trouble getting the first image to fade into the second image. As of now, it just fades out and that is it. I have my code below.

fade_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
  android:interpolator="@android:anim/linear_interpolator">
  <alpha
      android:fromAlpha="0.1"
      android:toAlpha="1.0"
      android:duration="5000"
      android:repeatCount="infinite"
      />
</set>

fade_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
  android:interpolator="@android:anim/linear_interpolator">
  <alpha
      android:fromAlpha="1.0"
      android:toAlpha="0.1"
      android:duration="5000"
      android:repeatCount="infinite"
      />
</set>

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/switcher"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:inAnimation="@anim/fade_in"
    android:outAnimation="@anim/fade_out" >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitCenter"
        android:src="@drawable/image1" />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitCenter"
        android:src="@drawable/image2" />
</ViewSwitcher>

MainClass.Activity

public class MainClass extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.next);

        slideshow();
    }

    public void slideshow() {
        ViewSwitcher switching = (ViewSwitcher)findViewById(R.id.switcher);
        if (switching.getDisplayedChild() == 0) {
            switching.showNext();
        } else {
            switching.showPrevious();
        }
    }

}
BossWalrus
  • 770
  • 1
  • 12
  • 29

1 Answers1

3

In that case, you need to use a timer. You use it like so:

public class MainClass extends Activity {

    private Timer timer;
    private ViewSwitcher switching;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.next);

        switching = (ViewSwitcher)findViewById(R.id.switcher);

        timer = new Timer();
        timer.scheduleAtFixedRate(new NextImageTask(), 0, 5000);
        //5000 is in milliseconds, meaning 5 seconds

    }

    public void slideshow() {
        if (switching.getDisplayedChild() == 0) {
            switching.showNext();
        } else {
            switching.showPrevious();
        }
    }

    private class NextImageTask extends TimerTask {

        @Override
        public void run() {
            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    slideshow();
                }
            });
        }
    }
}

What does this chunk of code do? Well, let's go at it step by step. First declare the views

private Timer timer;
private ViewSwitcher switching;

And then initialize them in the onCreate method

switching = (ViewSwitcher)findViewById(R.id.switcher);

timer = new Timer();

Then we start the timer! To start a timer and tell it what to do, we do it like so

timer.scheduleAtFixedRate(new NextImageTask(), 0, 5000);

This line of code basically means Hey timer, schedule a task at a fixed rate of 5 seconds. Start immediately!

The first argument is the task to be scheduled, an object, the NextImageTask(). This object contains a Runnable that contains the code to run every interval. The interval is a fixed rate of 5 seconds. In the code however it is written as 5000. This is because the method accepts the third argument as millisecond. To get 5 seconds, we must multiply 5 by 1,000 which results to, yep you guessed it right, 5,000. The timer is asked to start immediately by passing a second argument as 0. This is the delay. If you pass 2000 there, the timer will start after a 2 second delay. Just like the third argument, the method accepts this second argument as millisecond.

Next is the method slideshow() which is the same as the OP. This is what the OP wants to do.

Lastly is the private object, NextImageTask().

private class NextImageTask extends TimerTask {

    @Override
    public void run() {
        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                slideshow();
            }
        });
    }
}

This is the task that will be done by the timer at the fixed rate/every 5 seconds. It should extend TimerTask for the timer to work properly. TimerTask is an abstract class so the NextImageTask() should implement one method, the run() method. This method should contain the code that the timer will run at a fixed interval. This runs on a different thread so if you need to do something in the UI just like the OP's case, we need to run on the UI thread. This is the reason why we called runOnUiThread here. Finally, inside is another runnable calling the OP's method slideshow().

Keale
  • 3,924
  • 3
  • 29
  • 46