Fix jank when expanding photo in ContactDetailActivity.
The bug is caused as follows. Tapping the photo invokes a
PhotoSelectionActivity. When it initially sets the photo, a relayout
request is made, which causes a jank if the animation is already
underway.
Instead, we now wait for the layout before starting the animation.
Add new utility class with static doAfterLayout() method, since this
code was duplicated in a couple of places.
Bug: 6000382
Change-Id: Ic32a3db1f8c0be99fe0c160debede71f882c73e7
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);
+ }
+}