0

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)
androidevil
  • 9,011
  • 14
  • 41
  • 79

1 Answers1

1

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.)

Cat
  • 66,919
  • 24
  • 133
  • 141
  • Thank you, but here apeears this message in my Eclipse: The method removeOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){}) is undefined for the type new ViewTreeObserver.OnGlobalLayoutListener(){} – androidevil Nov 26 '12 at 19:05
  • I've got this error in my logcat: unable to resolve virtual method removeOnGlobalLayoutListener. Some idea to fix it? – androidevil Nov 26 '12 at 19:20
  • What device/API level are you running on? – Cat Nov 26 '12 at 19:25
  • My app is from API level 7, and I'm running on a device with 2.1-update 1 version – androidevil Nov 26 '12 at 19:32
  • Ah, yes. As my note says, for APIs under 16, you need to use `removeGlobalOnLayoutListener()` (notice **removeGlobalOn**, not **removeOnGlobal**). I have edited the code in my post to reflect this. – Cat Nov 26 '12 at 19:34
  • @user1771682 Sorry, obviously not on my game today. Updated the solution again. (The issue was that keeping the `final ViewTreeObserver` is not allowed; it expires before `onGlobalLayout()` is called.) – Cat Nov 26 '12 at 20:39