13efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang/* 23efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * Copyright (C) 2015 The Android Open Source Project 33efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * 43efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * Licensed under the Apache License, Version 2.0 (the "License"); 53efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * you may not use this file except in compliance with the License. 63efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * You may obtain a copy of the License at 73efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * 83efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * http://www.apache.org/licenses/LICENSE-2.0 93efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * 103efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * Unless required by applicable law or agreed to in writing, software 113efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * distributed under the License is distributed on an "AS IS" BASIS, 123efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * See the License for the specific language governing permissions and 143efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * limitations under the License. 153efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang */ 163efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 173efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangpackage com.android.contacts.editor; 183efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 193efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.content.Context; 203efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.graphics.Bitmap; 213efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.net.Uri; 223efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.provider.ContactsContract; 233efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.util.AttributeSet; 241044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jangimport android.util.TypedValue; 253efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.view.View; 261044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jangimport android.view.ViewGroup; 27ff16eea0e4d18cf2964667ce8e597780797e2b69Walter Jangimport android.widget.RelativeLayout; 283efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 290a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.ContactPhotoManager; 3065971d0f87dbee0b5ff93a7d64cdaab0940f56f5Gary Maiimport com.android.contacts.R; 3169c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.ValuesDelta; 3269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.util.MaterialColorMapUtils.MaterialPalette; 3365971d0f87dbee0b5ff93a7d64cdaab0940f56f5Gary Maiimport com.android.contacts.util.SchedulingUtils; 3465971d0f87dbee0b5ff93a7d64cdaab0940f56f5Gary Maiimport com.android.contacts.widget.QuickContactImageView; 3565971d0f87dbee0b5ff93a7d64cdaab0940f56f5Gary Mai 363efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang/** 3731a74ad969b650eb733e536569254ed3978c4f54Walter Jang * Displays a photo and calls the host back when the user clicks it. 383efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang */ 39363af60ea23e5a3b945005712a16564ab69db18bGary Maipublic class PhotoEditorView extends RelativeLayout implements View.OnClickListener { 403efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 4131a74ad969b650eb733e536569254ed3978c4f54Walter Jang /** 4231a74ad969b650eb733e536569254ed3978c4f54Walter Jang * Callbacks for the host of this view. 4331a74ad969b650eb733e536569254ed3978c4f54Walter Jang */ 4431a74ad969b650eb733e536569254ed3978c4f54Walter Jang public interface Listener { 4531a74ad969b650eb733e536569254ed3978c4f54Walter Jang 4631a74ad969b650eb733e536569254ed3978c4f54Walter Jang /** 4731a74ad969b650eb733e536569254ed3978c4f54Walter Jang * Invoked when the user wants to change their photo. 4831a74ad969b650eb733e536569254ed3978c4f54Walter Jang */ 4931a74ad969b650eb733e536569254ed3978c4f54Walter Jang void onPhotoEditorViewClicked(); 5031a74ad969b650eb733e536569254ed3978c4f54Walter Jang } 513efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 5231a74ad969b650eb733e536569254ed3978c4f54Walter Jang private Listener mListener; 533efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 541044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang private final float mLandscapePhotoRatio; 559d8f37e77052543c4ae07cbf8329e4ff0ddef66bWalter Jang private final float mPortraitPhotoRatio; 561044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang private final boolean mIsTwoPanel; 571044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang 58f46abd89a3386cbdadff99e96df826bb27f987e9Walter Jang private QuickContactImageView mPhotoImageView; 59ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang private View mPhotoIcon; 604a268d3dc9eb0fa067b1e408199ec7c969f34a25Walter Jang private View mPhotoIconOverlay; 61ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang private View mPhotoTouchInterceptOverlay; 6218724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai private MaterialPalette mMaterialPalette; 633efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 6431a74ad969b650eb733e536569254ed3978c4f54Walter Jang private boolean mReadOnly; 6531a74ad969b650eb733e536569254ed3978c4f54Walter Jang private boolean mIsNonDefaultPhotoBound; 6631a74ad969b650eb733e536569254ed3978c4f54Walter Jang 67363af60ea23e5a3b945005712a16564ab69db18bGary Mai public PhotoEditorView(Context context) { 681044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang this(context, null); 693efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 703efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 71363af60ea23e5a3b945005712a16564ab69db18bGary Mai public PhotoEditorView(Context context, AttributeSet attrs) { 723efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang super(context, attrs); 7331a74ad969b650eb733e536569254ed3978c4f54Walter Jang 74261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang mLandscapePhotoRatio = getTypedFloat(R.dimen.quickcontact_landscape_photo_ratio); 759d8f37e77052543c4ae07cbf8329e4ff0ddef66bWalter Jang mPortraitPhotoRatio = getTypedFloat(R.dimen.editor_portrait_photo_ratio); 76caf26197087343fdc18739e20e217236ff26831eWenyi Wang mIsTwoPanel = getResources().getBoolean(R.bool.contacteditor_two_panel); 773efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 783efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 79261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang private float getTypedFloat(int resourceId) { 80261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang final TypedValue typedValue = new TypedValue(); 81261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang getResources().getValue(resourceId, typedValue, /* resolveRefs =*/ true); 82261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang return typedValue.getFloat(); 83261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang } 84261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang 853efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang @Override 863efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang protected void onFinishInflate() { 873efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang super.onFinishInflate(); 88f46abd89a3386cbdadff99e96df826bb27f987e9Walter Jang mPhotoImageView = (QuickContactImageView) findViewById(R.id.photo); 89ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang mPhotoIcon = findViewById(R.id.photo_icon); 904a268d3dc9eb0fa067b1e408199ec7c969f34a25Walter Jang mPhotoIconOverlay = findViewById(R.id.photo_icon_overlay); 91ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang mPhotoTouchInterceptOverlay = findViewById(R.id.photo_touch_intercept_overlay); 92eec6992932cc1b650211402a30650c5842cc8ad8Gary Mai 933efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 943efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 9531a74ad969b650eb733e536569254ed3978c4f54Walter Jang public void setListener(Listener listener) { 9631a74ad969b650eb733e536569254ed3978c4f54Walter Jang mListener = listener; 9731a74ad969b650eb733e536569254ed3978c4f54Walter Jang } 983efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 9931a74ad969b650eb733e536569254ed3978c4f54Walter Jang public void setReadOnly(boolean readOnly) { 10031a74ad969b650eb733e536569254ed3978c4f54Walter Jang mReadOnly = readOnly; 101ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang if (mReadOnly) { 102ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang mPhotoIcon.setVisibility(View.GONE); 103ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang mPhotoIconOverlay.setVisibility(View.GONE); 1044ceabed629c43cb247fd4a0faa36c09bd5ec999aGary Mai mPhotoTouchInterceptOverlay.setClickable(false); 10534047d2d076f5501ff958f0ef041b4e25c65bbedGary Mai mPhotoTouchInterceptOverlay.setContentDescription(getContext().getString( 10634047d2d076f5501ff958f0ef041b4e25c65bbedGary Mai R.string.editor_contact_photo_content_description)); 107ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang } else { 1084ceabed629c43cb247fd4a0faa36c09bd5ec999aGary Mai mPhotoIcon.setVisibility(View.VISIBLE); 1094ceabed629c43cb247fd4a0faa36c09bd5ec999aGary Mai mPhotoIconOverlay.setVisibility(View.VISIBLE); 110ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang mPhotoTouchInterceptOverlay.setOnClickListener(this); 111ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai updatePhotoDescription(); 112ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang } 113fa127a1c0ca95139664771edc3d5d97331c93b19Walter Jang } 114fa127a1c0ca95139664771edc3d5d97331c93b19Walter Jang 11518724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai public void setPalette(MaterialPalette palette) { 11618724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai mMaterialPalette = palette; 11718724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai } 11818724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai 119fa127a1c0ca95139664771edc3d5d97331c93b19Walter Jang /** 12031a74ad969b650eb733e536569254ed3978c4f54Walter Jang * Tries to bind a full size photo or a bitmap loaded from the given ValuesDelta, 12131a74ad969b650eb733e536569254ed3978c4f54Walter Jang * and falls back to the default avatar, tinted using the given MaterialPalette (if it's not 12231a74ad969b650eb733e536569254ed3978c4f54Walter Jang * null); 123fa127a1c0ca95139664771edc3d5d97331c93b19Walter Jang */ 12418724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai public void setPhoto(ValuesDelta valuesDelta) { 12531a74ad969b650eb733e536569254ed3978c4f54Walter Jang // Check if we can update to the full size photo immediately 12631a74ad969b650eb733e536569254ed3978c4f54Walter Jang final Long photoFileId = EditorUiUtils.getPhotoFileId(valuesDelta); 12731a74ad969b650eb733e536569254ed3978c4f54Walter Jang if (photoFileId != null) { 12831a74ad969b650eb733e536569254ed3978c4f54Walter Jang final Uri photoUri = ContactsContract.DisplayPhoto.CONTENT_URI.buildUpon() 12931a74ad969b650eb733e536569254ed3978c4f54Walter Jang .appendPath(photoFileId.toString()).build(); 13031a74ad969b650eb733e536569254ed3978c4f54Walter Jang setFullSizedPhoto(photoUri); 13131a74ad969b650eb733e536569254ed3978c4f54Walter Jang adjustDimensions(); 13231a74ad969b650eb733e536569254ed3978c4f54Walter Jang return; 1333efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 1341044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang 13531a74ad969b650eb733e536569254ed3978c4f54Walter Jang // Use the bitmap image from the values delta 13631a74ad969b650eb733e536569254ed3978c4f54Walter Jang final Bitmap bitmap = EditorUiUtils.getPhotoBitmap(valuesDelta); 13731a74ad969b650eb733e536569254ed3978c4f54Walter Jang if (bitmap != null) { 13831a74ad969b650eb733e536569254ed3978c4f54Walter Jang setPhoto(bitmap); 13931a74ad969b650eb733e536569254ed3978c4f54Walter Jang adjustDimensions(); 14031a74ad969b650eb733e536569254ed3978c4f54Walter Jang return; 141f46abd89a3386cbdadff99e96df826bb27f987e9Walter Jang } 142f46abd89a3386cbdadff99e96df826bb27f987e9Walter Jang 14318724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai setDefaultPhoto(mMaterialPalette); 14431a74ad969b650eb733e536569254ed3978c4f54Walter Jang adjustDimensions(); 14531a74ad969b650eb733e536569254ed3978c4f54Walter Jang } 14631a74ad969b650eb733e536569254ed3978c4f54Walter Jang 14731a74ad969b650eb733e536569254ed3978c4f54Walter Jang private void adjustDimensions() { 14831a74ad969b650eb733e536569254ed3978c4f54Walter Jang // Follow the same logic as MultiShrinkScroll.initialize 1491044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang SchedulingUtils.doOnPreDraw(this, /* drawNextFrame =*/ false, new Runnable() { 1501044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang @Override 1511044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang public void run() { 152a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang final int photoHeight, photoWidth; 153a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang if (mIsTwoPanel) { 154eec6992932cc1b650211402a30650c5842cc8ad8Gary Mai photoHeight = getHeight(); 155a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang photoWidth = (int) (photoHeight * mLandscapePhotoRatio); 156a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang } else { 1579d8f37e77052543c4ae07cbf8329e4ff0ddef66bWalter Jang // Make the photo slightly shorter that it is wide 158eec6992932cc1b650211402a30650c5842cc8ad8Gary Mai photoWidth = getWidth(); 1599d8f37e77052543c4ae07cbf8329e4ff0ddef66bWalter Jang photoHeight = (int) (photoWidth / mPortraitPhotoRatio); 160a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang } 1611044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang final ViewGroup.LayoutParams layoutParams = getLayoutParams(); 1621044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang layoutParams.height = photoHeight; 163a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang layoutParams.width = photoWidth; 1641044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang setLayoutParams(layoutParams); 1651044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang } 1661044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang }); 1673efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 1683efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 1693efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang /** 17031a74ad969b650eb733e536569254ed3978c4f54Walter Jang * Whether a removable, non-default photo is bound to this view. 1713efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang */ 1723efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang public boolean isWritablePhotoSet() { 17331a74ad969b650eb733e536569254ed3978c4f54Walter Jang return !mReadOnly && mIsNonDefaultPhotoBound; 1743efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 1753efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 1763efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang /** 17731a74ad969b650eb733e536569254ed3978c4f54Walter Jang * Binds the given bitmap. 1783efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang */ 17931a74ad969b650eb733e536569254ed3978c4f54Walter Jang private void setPhoto(Bitmap bitmap) { 18031a74ad969b650eb733e536569254ed3978c4f54Walter Jang mPhotoImageView.setImageBitmap(bitmap); 18131a74ad969b650eb733e536569254ed3978c4f54Walter Jang mIsNonDefaultPhotoBound = true; 182ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai updatePhotoDescription(); 18331a74ad969b650eb733e536569254ed3978c4f54Walter Jang } 1843efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 18531a74ad969b650eb733e536569254ed3978c4f54Walter Jang private void setDefaultPhoto(MaterialPalette materialPalette) { 186da20b47c2b85390a2c3772379e71203c5aab513cGary Mai mIsNonDefaultPhotoBound = false; 187ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai updatePhotoDescription(); 18831a74ad969b650eb733e536569254ed3978c4f54Walter Jang EditorUiUtils.setDefaultPhoto(mPhotoImageView, getResources(), materialPalette); 1893efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 1903efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 191ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai private void updatePhotoDescription() { 192ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai mPhotoTouchInterceptOverlay.setContentDescription(getContext().getString( 193ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai mIsNonDefaultPhotoBound 194ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai ? R.string.editor_change_photo_content_description 195ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai : R.string.editor_add_photo_content_description)); 196ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai } 1973efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang /** 19831a74ad969b650eb733e536569254ed3978c4f54Walter Jang * Binds a full size photo loaded from the given Uri. 1993efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang */ 20031a74ad969b650eb733e536569254ed3978c4f54Walter Jang public void setFullSizedPhoto(Uri photoUri) { 20131a74ad969b650eb733e536569254ed3978c4f54Walter Jang EditorUiUtils.loadPhoto(ContactPhotoManager.getInstance(getContext()), 20231a74ad969b650eb733e536569254ed3978c4f54Walter Jang mPhotoImageView, photoUri); 20331a74ad969b650eb733e536569254ed3978c4f54Walter Jang mIsNonDefaultPhotoBound = true; 204ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai updatePhotoDescription(); 2051573aa697284e6627c7bb74eae4c350f56780c33Walter Jang } 2061573aa697284e6627c7bb74eae4c350f56780c33Walter Jang 2073efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang /** 20831a74ad969b650eb733e536569254ed3978c4f54Walter Jang * Removes the current bound photo bitmap. 2093efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang */ 21031a74ad969b650eb733e536569254ed3978c4f54Walter Jang public void removePhoto() { 21118724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai setDefaultPhoto(mMaterialPalette); 2123efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 2133efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang 2143efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang @Override 2153efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang public void onClick(View view) { 21631a74ad969b650eb733e536569254ed3978c4f54Walter Jang if (mListener != null) { 21731a74ad969b650eb733e536569254ed3978c4f54Walter Jang mListener.onPhotoEditorViewClicked(); 2183efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 2193efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang } 2203efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang} 221