PhotoSelectionActivity.java revision 51f9c0f2f2923d14cced5096b40f017dd87b68d3
16fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro/*
26fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * Copyright (C) 2011 The Android Open Source Project
36fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro *
46fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * Licensed under the Apache License, Version 2.0 (the "License");
56fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * you may not use this file except in compliance with the License.
66fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * You may obtain a copy of the License at
76fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro *
86fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro *      http://www.apache.org/licenses/LICENSE-2.0
96fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro *
106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * Unless required by applicable law or agreed to in writing, software
116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * distributed under the License is distributed on an "AS IS" BASIS,
126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * See the License for the specific language governing permissions and
146fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * limitations under the License.
156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */
166fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoropackage com.android.contacts.activities;
176fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1814d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoroimport com.android.contacts.ContactPhotoManager;
196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport com.android.contacts.ContactSaveService;
206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport com.android.contacts.R;
216fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport com.android.contacts.detail.PhotoSelectionHandler;
226fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport com.android.contacts.editor.PhotoActionPopup;
236fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport com.android.contacts.model.EntityDeltaList;
2451f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargusimport com.android.contacts.util.AnimationUtils;
256fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
266fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.animation.Animator;
276fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.animation.AnimatorListenerAdapter;
286fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.animation.ObjectAnimator;
296fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.animation.PropertyValuesHolder;
306fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.app.Activity;
316fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.content.Context;
326fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.content.Intent;
336fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.graphics.Bitmap;
346fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.graphics.Rect;
3514d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoroimport android.net.Uri;
366fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.os.Bundle;
376fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.os.Parcelable;
386fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.view.View;
396fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.view.ViewGroup.MarginLayoutParams;
406fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.view.ViewTreeObserver.OnGlobalLayoutListener;
416fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.widget.FrameLayout.LayoutParams;
426fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport android.widget.ImageView;
436fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
446fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport java.io.File;
456fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
466fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro/**
476fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * Popup activity for choosing a contact photo within the Contacts app.
486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */
496fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoropublic class PhotoSelectionActivity extends Activity {
506fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
516fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Number of ms for the animation to expand the photo. */
526fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private static final int PHOTO_EXPAND_DURATION = 100;
536fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
546fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Number of ms for the animation to contract the photo on activity exit. */
556fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private static final int PHOTO_CONTRACT_DURATION = 50;
566fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
576fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Number of ms for the animation to hide the backdrop on finish. */
586fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private static final int BACKDROP_FADEOUT_DURATION = 100;
596fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
606fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private static final String KEY_CURRENT_PHOTO_FILE = "currentphotofile";
616fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
626fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private static final String KEY_SUB_ACTIVITY_IN_PROGRESS = "subinprogress";
636fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
6414d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro    /** Intent extra to get the photo URI. */
6514d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro    public static final String PHOTO_URI = "photo_uri";
666fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Intent extra to get the entity delta list. */
686fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    public static final String ENTITY_DELTA_LIST = "entity_delta_list";
696fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
706fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Intent extra to indicate whether the contact is the user's profile. */
716fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    public static final String IS_PROFILE = "is_profile";
726fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
736fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Intent extra to indicate whether the contact is from a directory (non-editable). */
746fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    public static final String IS_DIRECTORY_CONTACT = "is_directory_contact";
756fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
766fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /**
776fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * Intent extra to indicate whether the photo should be animated to show the full contents of
786fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * the photo (on a larger portion of the screen) when clicked.  If unspecified or false, the
796fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * photo will not move from its original location.
806fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     */
816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    public static final String EXPAND_PHOTO = "expand_photo";
826fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
836fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Source bounds of the image that was clicked on. */
846fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private Rect mSourceBounds;
856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
8614d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro    /**
8714d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro     * The photo URI. May be null, in which case the default avatar will be used.
8814d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro     */
8914d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro    private Uri mPhotoUri;
906fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Entity delta list of the contact. */
926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private EntityDeltaList mState;
936fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
946fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Whether the contact is the user's profile. */
956fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private boolean mIsProfile;
966fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Whether the contact is from a directory. */
986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private boolean mIsDirectoryContact;
996fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Whether to animate the photo to an expanded view covering more of the screen. */
1016fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private boolean mExpandPhoto;
1026fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1036fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** The semi-transparent backdrop. */
1046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private View mBackdrop;
1056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1066fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** The photo view. */
1076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private ImageView mPhotoView;
1086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1096fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** The photo handler attached to this activity, if any. */
1106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private PhotoHandler mPhotoHandler;
1116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Animator to expand the photo out to full size. */
1136fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private ObjectAnimator mPhotoAnimator;
1146fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Listener for the animation. */
1166fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private AnimatorListenerAdapter mAnimationListener;
1176fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Whether a change in layout of the photo has occurred that has no animation yet. */
1196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private boolean mAnimationPending;
1206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1216fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Prior position of the image (for animating). */
1226fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    Rect mOriginalPos = new Rect();
1236fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1246fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Layout params for the photo view before we started animating. */
1256fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private LayoutParams mPhotoStartParams;
1266fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1276fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Layout params for the photo view after we finished animating. */
1286fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private LayoutParams mPhotoEndParams;
1296fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1306fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /** Whether a sub-activity is currently in progress. */
1316fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private boolean mSubActivityInProgress;
1326fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1336fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /**
1346fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * A photo result received by the activity, persisted across activity lifecycle.
1356fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     */
1366fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private PendingPhotoResult mPendingPhotoResult;
1376fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1386fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /**
1396fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * The photo file being interacted with, if any.  Saved/restored between activity instances.
1406fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     */
1416fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private File mCurrentPhotoFile;
1426fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1436fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    @Override
1446fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    protected void onCreate(Bundle savedInstanceState) {
1456fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        super.onCreate(savedInstanceState);
1466fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        setContentView(R.layout.photoselection_activity);
1476fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (savedInstanceState != null) {
1486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            String fileName = savedInstanceState.getString(KEY_CURRENT_PHOTO_FILE);
1496fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            if (fileName != null) {
1506fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mCurrentPhotoFile = new File(fileName);
1516fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
1526fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mSubActivityInProgress = savedInstanceState.getBoolean(KEY_SUB_ACTIVITY_IN_PROGRESS);
1536fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
1546fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1556fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        // Pull data out of the intent.
1566fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        final Intent intent = getIntent();
15714d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mPhotoUri = intent.getParcelableExtra(PHOTO_URI);
1586fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mState = (EntityDeltaList) intent.getParcelableExtra(ENTITY_DELTA_LIST);
1596fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mIsProfile = intent.getBooleanExtra(IS_PROFILE, false);
1606fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mIsDirectoryContact = intent.getBooleanExtra(IS_DIRECTORY_CONTACT, false);
1616fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mExpandPhoto = intent.getBooleanExtra(EXPAND_PHOTO, false);
1626fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1636fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mBackdrop = findViewById(R.id.backdrop);
1646fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mPhotoView = (ImageView) findViewById(R.id.photo);
1656fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mSourceBounds = intent.getSourceBounds();
1666fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        // Fade in the background.
1686fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        animateInBackground();
1696fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1706fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        // Dismiss the dialog on clicking the backdrop.
1716fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mBackdrop.setOnClickListener(new View.OnClickListener() {
1726fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
1736fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onClick(View v) {
1746fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                finish();
1756fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
1766fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        });
1776fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1786fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        // Wait until the layout pass to show the photo, so that the source bounds will match up.
17951f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus        AnimationUtils.doAfterLayout(mBackdrop, new Runnable() {
1806fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
18151f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus            public void run() {
1826fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                displayPhoto();
1836fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
18451f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus        });
1856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
1866fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1876fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    @Override
1886fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    public void finish() {
1896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (!mSubActivityInProgress) {
1906fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            closePhotoAndFinish();
1916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        } else {
1926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            activityFinish();
1936fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
1946fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
1956fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
1966fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /**
1976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * Builds a well-formed intent for invoking this activity.
1986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * @param context The context.
19914d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro     * @param photoUri The URI of the current photo (may be null, in which case the default
20014d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro     *     avatar image will be displayed).
20114d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro     * @param photoBitmap The bitmap of the current photo (may be null, in which case the default
20214d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro     *     avatar image will be displayed).
20314d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro     * @param photoBytes The bytes for the current photo (may be null, in which case the default
20414d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro     *     avatar image will be displayed).
2056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * @param photoBounds The pixel bounds of the current photo.
2066fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * @param delta The entity delta list for the contact.
2076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * @param isProfile Whether the contact is the user's profile.
2086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * @param isDirectoryContact Whether the contact comes from a directory (non-editable).
2096fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * @param expandPhotoOnClick Whether the photo should be expanded on click or not (generally,
2106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     *     this should be true for phones, and false for tablets).
2116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * @return An intent that can be used to invoke the photo selection activity.
2126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     */
21314d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro    public static Intent buildIntent(Context context, Uri photoUri, Bitmap photoBitmap,
21414d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            byte[] photoBytes, Rect photoBounds, EntityDeltaList delta, boolean isProfile,
21514d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            boolean isDirectoryContact, boolean expandPhotoOnClick) {
2166fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        Intent intent = new Intent(context, PhotoSelectionActivity.class);
21714d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        if (photoUri != null && photoBitmap != null && photoBytes != null) {
21814d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            intent.putExtra(PHOTO_URI, photoUri);
21914d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        }
2206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        intent.setSourceBounds(photoBounds);
2216fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        intent.putExtra(ENTITY_DELTA_LIST, (Parcelable) delta);
2226fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        intent.putExtra(IS_PROFILE, isProfile);
2236fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        intent.putExtra(IS_DIRECTORY_CONTACT, isDirectoryContact);
2246fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        intent.putExtra(EXPAND_PHOTO, expandPhotoOnClick);
2256fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        return intent;
2266fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
2276fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
2286fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private void activityFinish() {
2296fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        super.finish();
2306fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
2316fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
2326fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    @Override
2336fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    protected void onDestroy() {
2346fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        super.onDestroy();
2356fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (mPhotoAnimator != null) {
2366fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mPhotoAnimator.cancel();
2376fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mPhotoAnimator = null;
2386fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
2396fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (mPhotoHandler != null) {
2406fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mPhotoHandler.destroy();
2416fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mPhotoHandler = null;
2426fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
2436fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
2446fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
2456fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private void displayPhoto() {
24614d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        // Load the photo.
24714d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        if (mPhotoUri != null) {
24814d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            // If we have a URI, the bitmap should be cached directly.
24914d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            ContactPhotoManager.getInstance(this).loadPhoto(mPhotoView, mPhotoUri, true, false);
25014d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        } else {
25114d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            // Fall back to avatar image.
25214d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            mPhotoView.setImageResource(ContactPhotoManager.getDefaultAvatarResId(true, false));
25314d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        }
25414d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro
25514d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        // Animate the photo view into its end location.
25614d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        final int[] pos = new int[2];
25714d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mBackdrop.getLocationOnScreen(pos);
25814d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        LayoutParams layoutParams = new LayoutParams(mSourceBounds.width(),
25914d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                mSourceBounds.height());
26014d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mOriginalPos.left = mSourceBounds.left - pos[0];
26114d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mOriginalPos.top = mSourceBounds.top - pos[1];
26214d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mOriginalPos.right = mOriginalPos.left + mSourceBounds.width();
26314d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mOriginalPos.bottom = mOriginalPos.top + mSourceBounds.height();
26414d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        layoutParams.setMargins(mOriginalPos.left, mOriginalPos.top, mOriginalPos.right,
26514d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                mOriginalPos.bottom);
26614d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mPhotoStartParams = layoutParams;
26714d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mPhotoView.setLayoutParams(layoutParams);
26814d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mPhotoView.requestLayout();
26914d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro
27014d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        mPhotoView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
27114d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            @Override
27214d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            public void onLayoutChange(View v, int left, int top, int right, int bottom,
27314d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
27414d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                if (mAnimationPending) {
27514d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                    mAnimationPending = false;
27614d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                    PropertyValuesHolder pvhLeft =
27714d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                            PropertyValuesHolder.ofInt("left", mOriginalPos.left, left);
27814d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                    PropertyValuesHolder pvhTop =
27914d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                            PropertyValuesHolder.ofInt("top", mOriginalPos.top, top);
28014d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                    PropertyValuesHolder pvhRight =
28114d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                            PropertyValuesHolder.ofInt("right", mOriginalPos.right, right);
28214d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                    PropertyValuesHolder pvhBottom =
28314d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                            PropertyValuesHolder.ofInt("bottom", mOriginalPos.bottom, bottom);
28414d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                    ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(mPhotoView,
28514d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                            pvhLeft, pvhTop, pvhRight, pvhBottom).setDuration(
28614d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                            PHOTO_EXPAND_DURATION);
28714d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                    if (mAnimationListener != null) {
28814d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                        anim.addListener(mAnimationListener);
2896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    }
29014d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro                    anim.start();
2916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                }
29214d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro            }
29314d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        });
29414d2083c4c4c52b0d8b600a93c294af32cd6a826Dave Santoro        attachPhotoHandler();
2956fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
2966fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
2976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private LayoutParams getPhotoEndParams() {
2986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (mPhotoEndParams == null) {
2996fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mPhotoEndParams = new LayoutParams(mPhotoStartParams);
3006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            if (mExpandPhoto) {
3016fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                Rect bounds = new Rect();
3026fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mBackdrop.getDrawingRect(bounds);
3036fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                if (bounds.height() > bounds.width()) {
3046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    //Take up full width.
3056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    mPhotoEndParams.width = bounds.width();
3066fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    mPhotoEndParams.height = bounds.width();
3076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                } else {
3086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    // Take up full height, leaving space for the popup.
3096fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    mPhotoEndParams.height = bounds.height() - 150;
3106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    mPhotoEndParams.width = bounds.height() - 150;
3116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                }
3126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mPhotoEndParams.topMargin = 0;
3136fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mPhotoEndParams.leftMargin = 0;
3146fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mPhotoEndParams.bottomMargin = mPhotoEndParams.height;
3156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mPhotoEndParams.rightMargin = mPhotoEndParams.width;
3166fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
3176fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
3186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        return mPhotoEndParams;
3196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
3206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3216fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private void animatePhotoOpen() {
3226fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mAnimationListener = new AnimatorListenerAdapter() {
3236fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            private void capturePhotoPos() {
3246fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mPhotoView.requestLayout();
3256fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mOriginalPos.left = mPhotoView.getLeft();
3266fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mOriginalPos.top = mPhotoView.getTop();
3276fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mOriginalPos.right = mPhotoView.getRight();
3286fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mOriginalPos.bottom = mPhotoView.getBottom();
3296fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
3306fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3316fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
3326fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onAnimationEnd(Animator animation) {
3336fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                capturePhotoPos();
3346fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                if (mPhotoHandler != null) {
3356fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    mPhotoHandler.onClick(mPhotoView);
3366fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                }
3376fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
3386fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3396fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
3406fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onAnimationCancel(Animator animation) {
3416fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                capturePhotoPos();
3426fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
3436fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        };
3446fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        animatePhoto(getPhotoEndParams());
3456fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
3466fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3476fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private void closePhotoAndFinish() {
3486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mAnimationListener = new AnimatorListenerAdapter() {
3496fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
3506fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onAnimationEnd(Animator animation) {
3516fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                // After the photo animates down, fade it away and finish.
3526fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                ObjectAnimator anim = ObjectAnimator.ofFloat(
3536fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                        mPhotoView, "alpha", 0f).setDuration(PHOTO_CONTRACT_DURATION);
3546fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                anim.addListener(new AnimatorListenerAdapter() {
3556fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    @Override
3566fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    public void onAnimationEnd(Animator animation) {
3576fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                        activityFinish();
3586fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    }
3596fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                });
3606fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                anim.start();
3616fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
3626fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        };
3636fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3646fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        // TODO: This won't animate in the right way if the rotation has changed since the activity
3656fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        // was first started.
3666fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        animatePhoto(mPhotoStartParams);
3676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        animateAwayBackground();
3686fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
3696fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3706fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private void animatePhoto(MarginLayoutParams to) {
3716fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        // Cancel any existing animation.
3726fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (mPhotoAnimator != null) {
3736fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mPhotoAnimator.cancel();
3746fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
3756fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3766fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mPhotoView.setLayoutParams(to);
3776fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mAnimationPending = true;
3786fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mPhotoView.requestLayout();
3796fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
3806fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private void animateInBackground() {
3826fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        ObjectAnimator.ofFloat(mBackdrop, "alpha", 0, 0.5f).setDuration(
3836fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                PHOTO_EXPAND_DURATION).start();
3846fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
3856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3866fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private void animateAwayBackground() {
3876fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        ObjectAnimator.ofFloat(mBackdrop, "alpha", 0f).setDuration(
3886fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                BACKDROP_FADEOUT_DURATION).start();
3896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
3906fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
3916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    @Override
3926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    protected void onSaveInstanceState(Bundle outState) {
3936fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        super.onSaveInstanceState(outState);
3946fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (mCurrentPhotoFile != null) {
3956fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            outState.putString(KEY_CURRENT_PHOTO_FILE, mCurrentPhotoFile.toString());
3966fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
3976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        outState.putBoolean(KEY_SUB_ACTIVITY_IN_PROGRESS, mSubActivityInProgress);
3986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
3996fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
4006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    @Override
4016fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
4026fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (mPhotoHandler != null) {
4036fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mSubActivityInProgress = false;
4046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            if (mPhotoHandler.handlePhotoActivityResult(requestCode, resultCode, data)) {
4056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                // Clear out any pending photo result.
4066fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mPendingPhotoResult = null;
4076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            } else {
4086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                // User returning to the photo selection activity.  Re-display options.
4096fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mPhotoHandler.onClick(mPhotoView);
4106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
4116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        } else {
4126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            // Create a pending photo result to be handled when the photo handler is created.
4136fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mPendingPhotoResult = new PendingPhotoResult(requestCode, resultCode, data);
4146fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
4156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
4166fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
4176fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private void attachPhotoHandler() {
418ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus        // Always provide the same two choices (take a photo with the camera, select a photo
419ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus        // from the gallery), but with slightly different wording.
420ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus        // Note: don't worry about this being a read-only contact; this code will not be invoked.
421ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus        int mode = (mPhotoUri == null) ? PhotoActionPopup.Modes.NO_PHOTO
422ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus                : PhotoActionPopup.Modes.PHOTO_DISALLOW_PRIMARY;
423ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus        // We don't want to provide a choice to remove the photo for two reasons:
424ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus        //   1) the UX designs don't call for it
425ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus        //   2) even if we wanted to, the implementation would be moderately hairy
426ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus        mode &= ~PhotoActionPopup.Flags.REMOVE_PHOTO;
427ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus
428ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus        mPhotoHandler = new PhotoHandler(this, mPhotoView, mode, mState);
4296fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (mPendingPhotoResult != null) {
4306fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mPhotoHandler.handlePhotoActivityResult(mPendingPhotoResult.mRequestCode,
4316fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    mPendingPhotoResult.mResultCode, mPendingPhotoResult.mData);
4326fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mPendingPhotoResult = null;
4336fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        } else {
43451f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus            // Setting the photo in displayPhoto() resulted in a relayout
43551f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus            // request... to avoid jank, wait until this layout has happened.
43651f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus            AnimationUtils.doAfterLayout(mBackdrop, new Runnable() {
43751f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus                @Override
43851f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus                public void run() {
43951f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus                    animatePhotoOpen();
44051f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus                }
44151f9c0f2f2923d14cced5096b40f017dd87b68d3Josh Gargus            });
4426fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
4436fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
4446fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
4456fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private final class PhotoHandler extends PhotoSelectionHandler {
4466fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        private PhotoHandler(Context context, View photoView, int photoMode,
4476fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                EntityDeltaList state) {
4486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            super(context, photoView, photoMode, mIsDirectoryContact, state);
4496fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            setListener(new PhotoListener(context, mIsProfile));
4506fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
4516fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
4526fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        private final class PhotoListener extends PhotoActionListener {
4536fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            private final Context mContext;
4546fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            private final boolean mIsProfile;
4556fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            private PhotoListener(Context context, boolean isProfile) {
4566fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mContext = context;
4576fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mIsProfile = isProfile;
4586fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
4596fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
4606fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
4616fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void startTakePhotoActivity(Intent intent, int requestCode, File photoFile) {
4626fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mSubActivityInProgress = true;
4636fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mCurrentPhotoFile = photoFile;
4646fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                startActivityForResult(intent, requestCode);
4656fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
4666fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
4676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
468e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus            public void startPickFromGalleryActivity(Intent intent, int requestCode,
469e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus                    File photoFile) {
4706fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mSubActivityInProgress = true;
471e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus                mCurrentPhotoFile = photoFile;
4726fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                startActivityForResult(intent, requestCode);
4736fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
4746fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
4756fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
4766fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onPhotoSelected(Bitmap bitmap) {
477e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus                EntityDeltaList delta = getDeltaForAttachingPhotoToContact();
478e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus                long rawContactId = getWritableEntityId();
479e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus                String filePath = mCurrentPhotoFile.getAbsolutePath();
4806fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                Intent intent = ContactSaveService.createSaveContactIntent(mContext, delta,
4816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                        "", 0, mIsProfile, PhotoSelectionActivity.class,
482e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus                        ContactEditorActivity.ACTION_SAVE_COMPLETED, rawContactId, filePath);
4836fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                startService(intent);
4846fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                finish();
4856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
4866fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
4876fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
4886fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public File getCurrentPhotoFile() {
4896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                return mCurrentPhotoFile;
4906fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
4916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
4926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
4936fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onPhotoSelectionDismissed() {
4946fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                if (!mSubActivityInProgress) {
4956fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    finish();
4966fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                }
4976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
4986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
4996fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
5006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
5016fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private static class PendingPhotoResult {
5026fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        private int mRequestCode;
5036fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        private int mResultCode;
5046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        private Intent mData;
5056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        private PendingPhotoResult(int requestCode, int resultCode, Intent data) {
5066fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mRequestCode = requestCode;
5076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mResultCode = resultCode;
5086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            mData = data;
5096fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
5106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
5116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro}
512