Fixed bug: newly added apps didn't show up immediately 

Now, whenever apps change visibility or are removed, we invalidate the bitmap cache for CellLayout

Change-Id: I883ea6cc07b1b09775bb7d262417acb34fbec3de
diff --git a/src/com/android/launcher2/BubbleTextView.java b/src/com/android/launcher2/BubbleTextView.java
index 348fe34..4d1dbf8 100644
--- a/src/com/android/launcher2/BubbleTextView.java
+++ b/src/com/android/launcher2/BubbleTextView.java
@@ -30,13 +30,14 @@
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
+import android.view.View;
 
 /**
  * TextView that draws a bubble behind the text. We cannot use a LineBackgroundSpan
  * because we want to make the bubble taller than the text and TextView's clip is
  * too aggressive.
  */
-public class BubbleTextView extends CacheableTextView {
+public class BubbleTextView extends CacheableTextView implements VisibilityChangedBroadcaster {
     static final float CORNER_RADIUS = 4.0f;
     static final float SHADOW_LARGE_RADIUS = 4.0f;
     static final float SHADOW_SMALL_RADIUS = 1.75f;
@@ -64,6 +65,8 @@
     private boolean mBackgroundSizeChanged;
     private Drawable mBackground;
 
+    private VisibilityChangedListener mOnVisibilityChangedListener;
+
     public BubbleTextView(Context context) {
         super(context);
         init();
@@ -240,6 +243,18 @@
         return result;
     }
 
+    public void setVisibilityChangedListener(VisibilityChangedListener listener) {
+        mOnVisibilityChangedListener = listener;
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        if (mOnVisibilityChangedListener != null) {
+            mOnVisibilityChangedListener.receiveVisibilityChangedMessage(this);
+        }
+        super.onVisibilityChanged(changedView, visibility);
+    }
+
     @Override
     public void draw(Canvas canvas) {
         if (mPressedOrFocusedBackground != null && (isPressed() || isFocused())) {
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 2ddebe7..2359e32 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -53,7 +53,7 @@
 
 import java.util.Arrays;
 
-public class CellLayout extends ViewGroup implements Dimmable {
+public class CellLayout extends ViewGroup implements Dimmable, VisibilityChangedListener {
     static final String TAG = "CellLayout";
 
     private int mCellWidth;
@@ -409,7 +409,11 @@
 
     private void invalidateCache() {
         mIsCacheDirty = true;
-        invalidateIfNeeded();
+        invalidate();
+    }
+
+    public void receiveVisibilityChangedMessage(View v) {
+        invalidateCache();
     }
 
     public void updateCache() {
@@ -620,10 +624,11 @@
 
             child.setId(childId);
 
-            // We might be in the middle or end of shrinking/fading to a dimmed view
-            // Make sure this view's alpha is set the same as all the rest of the views
-            child.setAlpha(getAlpha());
             addView(child, index, lp);
+            if (child instanceof VisibilityChangedBroadcaster) {
+                VisibilityChangedBroadcaster v = (VisibilityChangedBroadcaster) child;
+                v.setVisibilityChangedListener(this);
+            }
 
             // invalidate the cache to have it reflect the new item
             invalidateCache();
@@ -649,34 +654,40 @@
     public void removeAllViews() {
         super.removeAllViews();
         clearOccupiedCells();
+        invalidateCache();
     }
 
     @Override
     public void removeAllViewsInLayout() {
         super.removeAllViewsInLayout();
         clearOccupiedCells();
+        invalidateCache();
     }
 
     public void removeViewWithoutMarkingCells(View view) {
         super.removeView(view);
+        invalidateCache();
     }
 
     @Override
     public void removeView(View view) {
         markCellsAsUnoccupiedForView(view);
         super.removeView(view);
+        invalidateCache();
     }
 
     @Override
     public void removeViewAt(int index) {
         markCellsAsUnoccupiedForView(getChildAt(index));
         super.removeViewAt(index);
+        invalidateCache();
     }
 
     @Override
     public void removeViewInLayout(View view) {
         markCellsAsUnoccupiedForView(view);
         super.removeViewInLayout(view);
+        invalidateCache();
     }
 
     @Override
@@ -685,6 +696,7 @@
             markCellsAsUnoccupiedForView(getChildAt(i));
         }
         super.removeViews(start, count);
+        invalidateCache();
     }
 
     @Override
@@ -693,6 +705,7 @@
             markCellsAsUnoccupiedForView(getChildAt(i));
         }
         super.removeViewsInLayout(start, count);
+        invalidateCache();
     }
 
     @Override
@@ -1713,3 +1726,14 @@
         }
     }
 }
+
+// Custom interfaces used to listen to "visibility changed" events of *children* of Views. Avoided
+// using "onVisibilityChanged" in the names because there's a method of that name in framework
+// (which can only can be used to listen to ancestors' "visibility changed" events)
+interface VisibilityChangedBroadcaster {
+    public void setVisibilityChangedListener(VisibilityChangedListener listener);
+}
+
+interface VisibilityChangedListener {
+    public void receiveVisibilityChangedMessage(View v);
+}
diff --git a/src/com/android/launcher2/LauncherAppWidgetHostView.java b/src/com/android/launcher2/LauncherAppWidgetHostView.java
index c45140e..85a80f9 100644
--- a/src/com/android/launcher2/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher2/LauncherAppWidgetHostView.java
@@ -28,13 +28,13 @@
 /**
  * {@inheritDoc}
  */
-public class LauncherAppWidgetHostView extends AppWidgetHostView {
+public class LauncherAppWidgetHostView extends AppWidgetHostView
+    implements VisibilityChangedBroadcaster {
     private boolean mHasPerformedLongPress;
-    
     private CheckForLongPress mPendingCheckForLongPress;
-    
     private LayoutInflater mInflater;
-    
+    private VisibilityChangedListener mOnVisibilityChangedListener;
+
     public LauncherAppWidgetHostView(Context context) {
         super(context);
         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -110,4 +110,16 @@
             removeCallbacks(mPendingCheckForLongPress);
         }
     }
+
+    public void setVisibilityChangedListener(VisibilityChangedListener listener) {
+        mOnVisibilityChangedListener = listener;
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        if (mOnVisibilityChangedListener != null) {
+            mOnVisibilityChangedListener.receiveVisibilityChangedMessage(this);
+        }
+        super.onVisibilityChanged(changedView, visibility);
+    }
 }