Merge "Fix jank when expanding photo in ContactDetailActivity."
diff --git a/src/com/android/contacts/activities/PhotoSelectionActivity.java b/src/com/android/contacts/activities/PhotoSelectionActivity.java
index 02843e9..1ac107b 100644
--- a/src/com/android/contacts/activities/PhotoSelectionActivity.java
+++ b/src/com/android/contacts/activities/PhotoSelectionActivity.java
@@ -21,6 +21,7 @@
 import com.android.contacts.detail.PhotoSelectionHandler;
 import com.android.contacts.editor.PhotoActionPopup;
 import com.android.contacts.model.EntityDeltaList;
+import com.android.contacts.util.AnimationUtils;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -175,14 +176,12 @@
         });
 
         // Wait until the layout pass to show the photo, so that the source bounds will match up.
-        OnGlobalLayoutListener globalLayoutListener = new OnGlobalLayoutListener() {
+        AnimationUtils.doAfterLayout(mBackdrop, new Runnable() {
             @Override
-            public void onGlobalLayout() {
+            public void run() {
                 displayPhoto();
-                mBackdrop.getViewTreeObserver().removeGlobalOnLayoutListener(this);
             }
-        };
-        mBackdrop.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);
+        });
     }
 
     @Override
@@ -432,7 +431,14 @@
                     mPendingPhotoResult.mResultCode, mPendingPhotoResult.mData);
             mPendingPhotoResult = null;
         } else {
-            animatePhotoOpen();
+            // Setting the photo in displayPhoto() resulted in a relayout
+            // request... to avoid jank, wait until this layout has happened.
+            AnimationUtils.doAfterLayout(mBackdrop, new Runnable() {
+                @Override
+                public void run() {
+                    animatePhotoOpen();
+                }
+            });
         }
     }
 
diff --git a/src/com/android/contacts/editor/EditorAnimator.java b/src/com/android/contacts/editor/EditorAnimator.java
index e1ad6d9..879b162 100644
--- a/src/com/android/contacts/editor/EditorAnimator.java
+++ b/src/com/android/contacts/editor/EditorAnimator.java
@@ -16,6 +16,8 @@
 
 package com.android.contacts.editor;
 
+import com.android.contacts.util.AnimationUtils;
+
 import com.google.common.collect.Lists;
 
 import android.animation.Animator;
@@ -87,7 +89,7 @@
         organizationSectionViewContainer.setVisibility(View.VISIBLE);
         organizationSectionViewContainer.setAlpha(0.0f);
         organizationSectionViewContainer.requestFocus();
-        doAfterLayout(addOrganizationButton, new Runnable() {
+        AnimationUtils.doAfterLayout(addOrganizationButton, new Runnable() {
             @Override
             public void run() {
                 // How many pixels extra do we need?
@@ -124,7 +126,7 @@
         // Make the new controls visible and do one layout pass (so that we can measure)
         view.setVisibility(View.VISIBLE);
         view.setAlpha(0.0f);
-        doAfterLayout(view, new Runnable() {
+        AnimationUtils.doAfterLayout(view, new Runnable() {
             @Override
             public void run() {
                 // How many pixels extra do we need?
@@ -182,19 +184,6 @@
         });
     }
 
-    /** Runs a piece of code after the next layout run */
-    private static void doAfterLayout(final View view, final Runnable runnable) {
-        final OnGlobalLayoutListener listener = new OnGlobalLayoutListener() {
-            @Override
-            public void onGlobalLayout() {
-                // Layout pass done, unregister for further events
-                view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                runnable.run();
-            }
-        };
-        view.getViewTreeObserver().addOnGlobalLayoutListener(listener);
-    }
-
     /**
      * Creates a translation-animation for the given views
      */
diff --git a/src/com/android/contacts/util/AnimationUtils.java b/src/com/android/contacts/util/AnimationUtils.java
new file mode 100644
index 0000000..31f0a0d
--- /dev/null
+++ b/src/com/android/contacts/util/AnimationUtils.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.util;
+
+import android.view.View;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+
+/** Static methods that are useful for animations. */
+public class AnimationUtils {
+
+    /** Runs a piece of code after the next layout run */
+    public static void doAfterLayout(final View view, final Runnable runnable) {
+        final OnGlobalLayoutListener listener = new OnGlobalLayoutListener() {
+            @Override
+            public void onGlobalLayout() {
+                // Layout pass done, unregister for further events
+                view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                runnable.run();
+            }
+        };
+        view.getViewTreeObserver().addOnGlobalLayoutListener(listener);
+    }
+}