1 package com.android.mail.utils; 2 3 import android.os.Handler; 4 import android.view.View; 5 import android.view.ViewTreeObserver; 6 7 /** 8 * Given a View to monitor draws on, an instance of this class will notify a listener of state 9 * changes between {@link #STATE_ACTIVE} and {@link #STATE_IDLE}. 10 * <p> 11 * Any drawing will instantly trigger {@link #STATE_ACTIVE}. {@link #STATE_IDLE} is only 12 * subsequently triggered if {@link #IDLE_WINDOW_MS} continuous milliseconds elapse with zero draws. 13 */ 14 public class DrawIdler { 15 16 public static final int STATE_IDLE = 0; 17 public static final int STATE_ACTIVE = 1; 18 19 private static final int IDLE_WINDOW_MS = 100; 20 21 private int mState = STATE_IDLE; 22 23 private View mRoot; 24 private IdleListener mListener; 25 private final IdleReader mIdleReader = new IdleReader(); 26 private final Handler mHandler = new Handler(); 27 28 public interface IdleListener { 29 void onStateChanged(DrawIdler idler, int newState); 30 } 31 32 public void setListener(IdleListener listener) { 33 mListener = listener; 34 if (mListener != null) { 35 mListener.onStateChanged(this, mState); 36 } 37 } 38 39 public void setRootView(View rootView) { 40 if (mRoot == rootView) { 41 return; 42 } else if (mRoot != null) { 43 mRoot.getViewTreeObserver().removeOnPreDrawListener(mIdleReader); 44 } 45 46 mRoot = rootView; 47 48 if (mRoot != null) { 49 mRoot.getViewTreeObserver().addOnPreDrawListener(mIdleReader); 50 } 51 } 52 53 public int getCurrentState() { 54 return mState; 55 } 56 57 private void setState(int newState) { 58 if (mState == newState) { 59 return; 60 } 61 mState = newState; 62 if (mListener != null) { 63 mListener.onStateChanged(this, newState); 64 } 65 } 66 67 // this inner class keeps implementation details private 68 // (we use OnPreDrawListener instead of OnDrawListener because the latter is only JB+) 69 private class IdleReader implements Runnable, ViewTreeObserver.OnPreDrawListener { 70 71 @Override 72 public void run() { 73 setState(STATE_IDLE); 74 } 75 76 @Override 77 public boolean onPreDraw() { 78 setState(STATE_ACTIVE); 79 mHandler.removeCallbacks(this); 80 mHandler.postDelayed(this, IDLE_WINDOW_MS); 81 return true; // always allow the draw; we're only here to observe 82 } 83 84 } 85 86 } 87