Merge "Make quickcontact launchable with am" into jb-dev
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index bcceff4..0502d4d 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -560,6 +560,11 @@
                 case ContactsRequest.ACTION_VIEW_CONTACT:
                     // We redirect this intent to the detail activity on 1-pane, so we don't get
                     // here.  It's only for 2-pane.
+                    Uri currentlyLoadedContactUri = mContactDetailFragment.getUri();
+                    if (currentlyLoadedContactUri != null
+                            && !mRequest.getContactUri().equals(currentlyLoadedContactUri)) {
+                        mContactDetailsView.setMaskVisibility(true);
+                    }
                     tabToOpen = TabState.ALL;
                     break;
                 case ContactsRequest.ACTION_GROUP:
@@ -612,7 +617,7 @@
         // If we are switching from one group to another, do a cross-fade
         if (mGroupDetailFragment != null && mGroupDetailFragment.getGroupUri() != null &&
                 !UriUtils.areEqual(mGroupDetailFragment.getGroupUri(), groupUri)) {
-            mGroupDetailsView.startTransition(mGroupDetailFragment.getView(), false);
+            mGroupDetailsView.startMaskTransition(false);
         }
         mGroupDetailFragment.loadGroup(groupUri);
         invalidateOptionsMenuIfNeeded();
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index c91f493..5c68dcb 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -356,6 +356,9 @@
         mShowStaticPhoto = showPhoto;
     }
 
+    /**
+     * Shows the contact detail with a message indicating there are no contact details.
+     */
     public void showEmptyState() {
         setData(null, null);
     }
@@ -406,6 +409,9 @@
 
         if (mContactData == null) {
             mView.setVisibility(View.INVISIBLE);
+            if (mStaticPhotoContainer != null) {
+                mStaticPhotoContainer.setVisibility(View.GONE);
+            }
             mAllEntries.clear();
             if (mAdapter != null) {
                 mAdapter.notifyDataSetChanged();
diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java
index a99f35f..e6a5984 100644
--- a/src/com/android/contacts/detail/ContactDetailLayoutController.java
+++ b/src/com/android/contacts/detail/ContactDetailLayoutController.java
@@ -291,8 +291,7 @@
         if (PhoneCapabilityTester.isUsingTwoPanes(mActivity)) {
             // Tablet: If we already showed data before, we want to cross-fade from screen to screen
             if (contactWasLoaded && mTransitionAnimationView != null && isDifferentContact) {
-                mTransitionAnimationView.startTransition(
-                        mViewContainer, mContactData == null);
+                mTransitionAnimationView.startMaskTransition(mContactData == null);
             }
         } else {
             // Small screen: We are on our own screen. Fade the data in, but only the first time
@@ -367,7 +366,7 @@
                     // This is screen is very hard to animate properly, because there is such a hard
                     // cut from the regular version. A proper animation would have to reflow text
                     // and move things around. Doing a simple cross-fade instead.
-                    mTransitionAnimationView.startTransition(mViewContainer, false);
+                    mTransitionAnimationView.startMaskTransition(false);
                 }
 
                 // Set the contact data (hide the static photo because the photo will already be in
diff --git a/src/com/android/contacts/util/ImageViewDrawableSetter.java b/src/com/android/contacts/util/ImageViewDrawableSetter.java
index 5cde022..1d23dd0 100644
--- a/src/com/android/contacts/util/ImageViewDrawableSetter.java
+++ b/src/com/android/contacts/util/ImageViewDrawableSetter.java
@@ -39,10 +39,10 @@
     private ImageView mTarget;
     private byte[] mCompressed;
     private Drawable mPreviousDrawable;
+    private int mDurationInMillis = 0;
     private static final String TAG = "ImageViewDrawableSetter";
 
     public ImageViewDrawableSetter() {
-
     }
 
     public ImageViewDrawableSetter(ImageView target) {
@@ -54,6 +54,10 @@
         setCompressedImage(contactData.getPhotoBinaryData());
     }
 
+    public void setTransitionDuration(int durationInMillis) {
+        mDurationInMillis = durationInMillis;
+    }
+
     public ImageView getTarget() {
         return mTarget;
     }
@@ -97,7 +101,7 @@
         // If we don't have a new Drawable, something went wrong... bail out.
         if (newDrawable == null) return previousBitmap();
 
-        if (mPreviousDrawable == null) {
+        if (mPreviousDrawable == null || mDurationInMillis == 0) {
             // Set the new one immediately.
             mTarget.setImageDrawable(newDrawable);
         } else {
@@ -107,7 +111,7 @@
             beforeAndAfter[1] = newDrawable;
             final TransitionDrawable transition = new TransitionDrawable(beforeAndAfter);
             mTarget.setImageDrawable(transition);
-            transition.startTransition(200);
+            transition.startTransition(mDurationInMillis);
         }
 
         // Remember this for next time, so that we can transition from it to the
diff --git a/src/com/android/contacts/widget/TransitionAnimationView.java b/src/com/android/contacts/widget/TransitionAnimationView.java
index cefc82d..28d728b 100644
--- a/src/com/android/contacts/widget/TransitionAnimationView.java
+++ b/src/com/android/contacts/widget/TransitionAnimationView.java
@@ -15,30 +15,20 @@
  */
 package com.android.contacts.widget;
 
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.ObjectAnimator;
 import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.drawable.BitmapDrawable;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.FrameLayout;
 
 /**
- * A container for a view that needs to have exit/enter animations when rebinding data.
- * After rebinding the contents, the following call should be made (where child is the only visible)
- * child
- * <pre>
- *   TransitionAnimationView.startAnimation(child);
- * </pre>
+ * A container that places a masking view on top of all other views.  The masking view can be
+ * faded in and out.  Currently, the masking view is solid color white.
  */
-public class TransitionAnimationView extends FrameLayout implements AnimatorListener {
-    private View mPreviousStateView;
-    private Bitmap mPreviousStateBitmap;
-    private ObjectAnimator mPreviousAnimator;
+public class TransitionAnimationView extends FrameLayout {
+    private View mMaskingView;
+    private ObjectAnimator mAnimator;
 
     public TransitionAnimationView(Context context) {
         this(context, null, 0);
@@ -55,75 +45,43 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mPreviousStateView = new View(getContext());
-        mPreviousStateView.setVisibility(View.INVISIBLE);
-        mPreviousStateView.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+        mMaskingView = new View(getContext());
+        mMaskingView.setVisibility(View.INVISIBLE);
+        mMaskingView.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                 LayoutParams.MATCH_PARENT));
-        addView(mPreviousStateView);
+        mMaskingView.setBackgroundColor(Color.WHITE);
+        addView(mMaskingView);
     }
 
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        mPreviousStateView.setBackgroundDrawable(null);
-        if (mPreviousStateBitmap != null) {
-            mPreviousStateBitmap.recycle();
-            mPreviousStateBitmap = null;
-        }
-    }
-
-    public void startTransition(View view, boolean closing) {
-        if (mPreviousAnimator != null && mPreviousAnimator.isRunning()) {
-            mPreviousAnimator.end();
-        }
-        if (view.getVisibility() != View.VISIBLE) {
-            if (!closing) {
-                mPreviousAnimator = ObjectAnimator.ofFloat(view, View.ALPHA, 0.0f, 1.0f);
-                mPreviousAnimator.start();
-            }
-        } else if (closing) {
-            mPreviousAnimator = ObjectAnimator.ofFloat(view, View.ALPHA, 1.0f, 0.0f);
-            mPreviousAnimator.start();
+    public void setMaskVisibility(boolean flag) {
+        if (flag) {
+            mMaskingView.setAlpha(1.0f);
+            mMaskingView.setVisibility(View.VISIBLE);
         } else {
-            if (view.getWidth() > 0 && view.getHeight() > 0) {
-                // Take a "screenshot" of the current state of the screen and show that on top
-                // of the real content. Then, fade that out.
-                mPreviousStateBitmap = Bitmap.createBitmap(
-                        view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
-                mPreviousStateView.setBackgroundDrawable(
-                        new BitmapDrawable(getContext().getResources(), mPreviousStateBitmap));
-                mPreviousStateView.setLayoutParams(view.getLayoutParams());
-                mPreviousStateBitmap.eraseColor(Color.WHITE);
-                Canvas canvas = new Canvas(mPreviousStateBitmap);
-                view.draw(canvas);
-                canvas.setBitmap(null);
-                mPreviousStateView.setVisibility(View.VISIBLE);
-
-                mPreviousAnimator =
-                        ObjectAnimator.ofFloat(mPreviousStateView, View.ALPHA, 1.0f, 0.0f);
-                mPreviousAnimator.start();
-            }
+            mMaskingView.setVisibility(View.INVISIBLE);
         }
     }
 
-    @Override
-    public void onAnimationEnd(Animator animation) {
-        mPreviousStateView.setVisibility(View.INVISIBLE);
-        mPreviousStateView.setBackgroundDrawable(null);
-        mPreviousStateBitmap.recycle();
-        mPreviousStateBitmap = null;
-        mPreviousAnimator = null;
-    }
+    /**
+     * Starts the transition of showing or hiding the mask.
+     * If showMask is true, the mask will be set to be invisible then fade into hide the other
+     * views in this container.  If showMask is false, the mask will be set to be hide other views
+     * initially.  Then, the other views in this container will be revealed.
+     */
+    public void startMaskTransition(boolean showMask) {
+        // Stop any animation that may still be running.
+        if (mAnimator != null && mAnimator.isRunning()) {
+            mAnimator.end();
+        }
 
-    @Override
-    public void onAnimationCancel(Animator animation) {
-    }
-
-    @Override
-    public void onAnimationStart(Animator animation) {
-    }
-
-    @Override
-    public void onAnimationRepeat(Animator animation) {
+        mMaskingView.setVisibility(View.VISIBLE);
+        if (showMask) {
+            mAnimator = ObjectAnimator.ofFloat(mMaskingView, View.ALPHA, 0.0f, 1.0f);
+            mAnimator.start();
+        } else {
+            // asked to hide the view
+            mAnimator = ObjectAnimator.ofFloat(mMaskingView, View.ALPHA, 1.0f, 0.0f);
+            mAnimator.start();
+        }
     }
 }