Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae846169 authored by Maurice Chu's avatar Maurice Chu Committed by Android Git Automerger
Browse files

am 1dec2e59: Merge "Fixed contact detail animated transitions" into jb-dev

* commit '1dec2e59':
  Fixed contact detail animated transitions
parents a5ad65b0 1dec2e59
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -560,6 +560,11 @@ public class PeopleActivity extends ContactsActivity
                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 @@ public class PeopleActivity extends ContactsActivity
        // 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();
+6 −0
Original line number Diff line number Diff line
@@ -356,6 +356,9 @@ public class ContactDetailFragment extends Fragment implements FragmentKeyListen
        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 @@ public class ContactDetailFragment extends Fragment implements FragmentKeyListen

        if (mContactData == null) {
            mView.setVisibility(View.INVISIBLE);
            if (mStaticPhotoContainer != null) {
                mStaticPhotoContainer.setVisibility(View.GONE);
            }
            mAllEntries.clear();
            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
+2 −3
Original line number Diff line number Diff line
@@ -291,8 +291,7 @@ public class ContactDetailLayoutController {
        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 @@ public class ContactDetailLayoutController {
                    // 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
+7 −3
Original line number Diff line number Diff line
@@ -39,10 +39,10 @@ public class ImageViewDrawableSetter {
    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 @@ public class ImageViewDrawableSetter {
        setCompressedImage(contactData.getPhotoBinaryData());
    }

    public void setTransitionDuration(int durationInMillis) {
        mDurationInMillis = durationInMillis;
    }

    public ImageView getTarget() {
        return mTarget;
    }
@@ -97,7 +101,7 @@ public class ImageViewDrawableSetter {
        // 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 @@ public class ImageViewDrawableSetter {
            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
+34 −76
Original line number Diff line number Diff line
@@ -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 @@ public class TransitionAnimationView extends FrameLayout implements AnimatorList
    @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;
    }

    @Override
    public void onAnimationCancel(Animator animation) {
    /**
     * 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 onAnimationStart(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();
        }

    @Override
    public void onAnimationRepeat(Animator animation) {
    }
}