Question

I have a class with a view for animation and a chronometer. This is the content of my onCreate method:

    chronometer = ((Chronometer) findViewById(R.id.clock_time));
    chronometer.setOnChronometerTickListener(this);

    chronometer.start();

    v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

    final SurfaceView surfaceViewTimer = (SurfaceView) findViewById(R.id.surface_view_timer);

    final RelativeLayout timeView = (RelativeLayout) findViewById(R.id.time_view);
    ViewTreeObserver observer = timeView.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            int animationDuration = getIntent().getIntExtra(
                    MainActivity.TOTAL_TIME, -1);
            TranslateAnimation surfaceGrowingAnimation = new TranslateAnimation(
                    0, 0, timeView.getHeight(), 0);

            surfaceGrowingAnimation.setDuration(animationDuration * 1000);          

            surfaceViewTimer.startAnimation(surfaceGrowingAnimation);

I have this other method to the chronometer:

@Override
public void onChronometerTick(Chronometer chronometer) {

    int intervalOfVibration = getIntent().getIntExtra(
            MainActivity.VIBRATION_INTERVAL, -1);

    long elapsedMillis = (SystemClock.elapsedRealtime() - ((Chronometer) findViewById(R.id.clock_time))
            .getBase()) / 1000;

    if (((elapsedMillis % intervalOfVibration) == 0) && (elapsedMillis > 0))
        v.vibrate(300);

}

But my animation restarts on each tick of the chronometer.

How can I fix this?

Now I get these errors:

11-26 17:58:57.908: W/dalvikvm(15596): threadid=3: thread exiting with uncaught exception (group=0x2aaca228)
11-26 17:58:57.908: E/AndroidRuntime(15596): Uncaught handler: thread main exiting due to uncaught exception
11-26 17:58:57.908: E/AndroidRuntime(15596): java.lang.IllegalStateException: This ViewTreeObserver is not alive, call getViewTreeObserver() again
11-26 17:58:57.908: E/AndroidRuntime(15596):    at android.view.ViewTreeObserver.checkIsAlive(ViewTreeObserver.java:492)
11-26 17:58:57.908: E/AndroidRuntime(15596):    at android.view.ViewTreeObserver.removeGlobalOnLayoutListener(ViewTreeObserver.java:339)
11-26 17:58:57.908: E/AndroidRuntime(15596):    at com.activities.TimerActivity$1.onGlobalLayout(TimerActivity.java:64)
11-26 17:58:57.908: E/AndroidRuntime(15596):    at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:549)
Was it helpful?

Solution

Your OnGlobalLayoutListener is being called every time the screen is laid out, which includes each time the Chronometer changes (since it changes width, possibly height, etc., and everything invalidates).

Use removeOnGlobalLayoutListener(); in your onGlobalLayout() method:

ViewTreeObserver observer = timeView.getViewTreeObserver(); // Make this final
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    @SuppressWarnings("deprecation")
    public void onGlobalLayout() {
        // Your code ...

        if (android.os.Build.VERSION.SDK_INT < 16) // Use old, deprecated method
            timeView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        else // Use new method
            timeView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
}

Note: You will have to use removeGlobalOnLayoutListener() instead, for APIs < 16. (The method name was changed in API level 16. They perform in an identical manner.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top