Alex
Alex

Reputation: 751

Firing an event as soon as activity is visible to the user

I wanted to create countdown as soon as the user sees an activity. However, there does not seem to be an appropriate callback for that. Neither onResume nor onWindowFocusChanged seem to be the correct callbacks, because the whole code is executed before the user even see anything. As a result I end up with "Go!" on the screen right from the start.

In a nutshell: Do you have any idea how to implement a countdown without any user interaction as soon as the activity is visible to the user?

EDIT:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.util.concurrent.TimeUnit;
import android.widget.TextView;

public class ChallengeModeTutorial extends AppCompatActivity {

    private void delayOneSec()
    {
        try
        {
            TimeUnit.SECONDS.sleep(2);
        }
        catch (InterruptedException e)
        {
            assert true;
        }
    }

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

    @Override
    public void onWindowFocusChanged(boolean hasFocus)
    {
        super.onWindowFocusChanged(hasFocus);
        TextView readySteadyGo = (TextView) findViewById(R.id.challengeModeTutorialReadySteadyGoTextView);
        // TextView tutorialText = (TextView) findViewById(R.id.challengeModeTutorialTextTextView);
        TextView timeUntilStart = (TextView) findViewById(R.id.challengeModeTutorialReadyTimeTextView);

        readySteadyGo.setText("");
        timeUntilStart.setText("5");
        delayOneSec();
        timeUntilStart.setText("4");
        delayOneSec();
        timeUntilStart.setText("3");
        delayOneSec();
        readySteadyGo.setText("Ready!");
        timeUntilStart.setText("2");
        delayOneSec();
        readySteadyGo.setText("Steady!");
        timeUntilStart.setText("1");
        delayOneSec();
        readySteadyGo.setText("");
        readySteadyGo.setText("Go!");
    }
}

Upvotes: 0

Views: 88

Answers (4)

Alex
Alex

Reputation: 751

I finally got it to work like this:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class ChallengeModeTutorial extends AppCompatActivity {

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

    @Override
    protected void onStart()
    {
        super.onStart();

        final TextView readySteadyGo = (TextView) findViewById(R.id.challengeModeTutorialReadySteadyGoTextView);
        final TextView timeUntilStart = (TextView) findViewById(R.id.challengeModeTutorialReadyTimeTextView);

        readySteadyGo.setText("");

        Thread t=new Thread(){

            @Override
            public void run(){

                while(continueThread){

                    try {
                        Thread.sleep(1000);

                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                if(currentCount > 0)
                                {
                                    timeUntilStart.setText(String.valueOf(currentCount));
                                }
                                else
                                {
                                    timeUntilStart.setText("Go!");
                                }
                                switch (currentCount)
                                {
                                    case 2: readySteadyGo.setText("Ready!"); break;
                                    case 1: readySteadyGo.setText("Steady!"); break;
                                    default: readySteadyGo.setText(""); break;
                                }
                                currentCount--;
                                if (currentCount == 0)
                                {
                                    continueThread = false;
                                }
                            }
                        });

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        };

        t.start();
    }

    private boolean continueThread = true;
    private int currentCount = 5;
}

Upvotes: 0

Budius
Budius

Reputation: 39836

The problem is that you're blocking the UI thread. When you call setText(String) it doesn't immediately gets drawn. The TextView gets invalidated and it will be draw on the next draw phase. But if you block the thread, this will never happen. You have to use a postDelayed() to execute the next setText(String) a second later.

Upvotes: 2

Christopher
Christopher

Reputation: 59

You can start your countdown, inside of your onStart method, which you need to overwrite.

The visible lifetime of an activity happens between a call to onStart() until a corresponding call to onStop(). During this time the user can see the activity on-screen, though it may not be in the foreground and interacting with the user.

From:
https://developer.android.com/reference/android/app/Activity

 @Override
protected void onStart() {
    super.onStart();
}

Upvotes: 0

user8118328
user8118328

Reputation: 703

I'm not sure if this works, but you could try using a ViewTreeObserver in onCreate. It gets called once the layout is drawn. (Replace LinearLayout with whatever Layout your "activity_challenge_mode_tutorial" actually is.)

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

    final LinearLayout layout = (LinearLayout) findViewById(R.id.YOUR_VIEW_ID);
    ViewTreeObserver vto = layout.getViewTreeObserver(); 
    vto.addOnGlobalLayoutListener (new OnGlobalLayoutListener() { 
        @Override 
        public void onGlobalLayout() {
            // Remove listener to prevent repeat calls.
            layout.getViewTreeObserver().removeOnGlobalLayoutListener(this); 

            // Start countdown here.

        } 
    });
}

Code is taken from this answer: https://stackoverflow.com/a/7735122/8118328

Upvotes: 0

Related Questions