package com.android.mail.utils; import android.os.Handler; import android.view.View; import android.view.ViewTreeObserver; /** * Given a View to monitor draws on, an instance of this class will notify a listener of state * changes between {@link #STATE_ACTIVE} and {@link #STATE_IDLE}. *

* Any drawing will instantly trigger {@link #STATE_ACTIVE}. {@link #STATE_IDLE} is only * subsequently triggered if {@link #IDLE_WINDOW_MS} continuous milliseconds elapse with zero draws. */ public class DrawIdler { public static final int STATE_IDLE = 0; public static final int STATE_ACTIVE = 1; private static final int IDLE_WINDOW_MS = 100; private int mState = STATE_IDLE; private View mRoot; private IdleListener mListener; private final IdleReader mIdleReader = new IdleReader(); private final Handler mHandler = new Handler(); public interface IdleListener { void onStateChanged(DrawIdler idler, int newState); } public void setListener(IdleListener listener) { mListener = listener; if (mListener != null) { mListener.onStateChanged(this, mState); } } public void setRootView(View rootView) { if (mRoot == rootView) { return; } else if (mRoot != null) { mRoot.getViewTreeObserver().removeOnPreDrawListener(mIdleReader); } mRoot = rootView; if (mRoot != null) { mRoot.getViewTreeObserver().addOnPreDrawListener(mIdleReader); } } public int getCurrentState() { return mState; } private void setState(int newState) { if (mState == newState) { return; } mState = newState; if (mListener != null) { mListener.onStateChanged(this, newState); } } // this inner class keeps implementation details private // (we use OnPreDrawListener instead of OnDrawListener because the latter is only JB+) private class IdleReader implements Runnable, ViewTreeObserver.OnPreDrawListener { @Override public void run() { setState(STATE_IDLE); } @Override public boolean onPreDraw() { setState(STATE_ACTIVE); mHandler.removeCallbacks(this); mHandler.postDelayed(this, IDLE_WINDOW_MS); return true; // always allow the draw; we're only here to observe } } }