blob: 09a15b09d8d7482443181dcbcab272dc6d229b80 [file] [log] [blame]
/*
* Copyright (C) 2015 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.editor;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.ContactsContract;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import com.android.contacts.ContactPhotoManager;
import com.android.contacts.R;
import com.android.contacts.model.ValuesDelta;
import com.android.contacts.util.MaterialColorMapUtils.MaterialPalette;
import com.android.contacts.util.SchedulingUtils;
import com.android.contacts.widget.QuickContactImageView;
/**
* Displays a photo and calls the host back when the user clicks it.
*/
public class PhotoEditorView extends RelativeLayout implements View.OnClickListener {
/**
* Callbacks for the host of this view.
*/
public interface Listener {
/**
* Invoked when the user wants to change their photo.
*/
void onPhotoEditorViewClicked();
}
private Listener mListener;
private final float mLandscapePhotoRatio;
private final float mPortraitPhotoRatio;
private final boolean mIsTwoPanel;
private QuickContactImageView mPhotoImageView;
private View mPhotoIcon;
private View mPhotoIconOverlay;
private View mPhotoTouchInterceptOverlay;
private MaterialPalette mMaterialPalette;
private boolean mReadOnly;
private boolean mIsNonDefaultPhotoBound;
public PhotoEditorView(Context context) {
this(context, null);
}
public PhotoEditorView(Context context, AttributeSet attrs) {
super(context, attrs);
mLandscapePhotoRatio = getTypedFloat(R.dimen.quickcontact_landscape_photo_ratio);
mPortraitPhotoRatio = getTypedFloat(R.dimen.editor_portrait_photo_ratio);
mIsTwoPanel = getResources().getBoolean(R.bool.contacteditor_two_panel);
}
private float getTypedFloat(int resourceId) {
final TypedValue typedValue = new TypedValue();
getResources().getValue(resourceId, typedValue, /* resolveRefs =*/ true);
return typedValue.getFloat();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mPhotoImageView = (QuickContactImageView) findViewById(R.id.photo);
mPhotoIcon = findViewById(R.id.photo_icon);
mPhotoIconOverlay = findViewById(R.id.photo_icon_overlay);
mPhotoTouchInterceptOverlay = findViewById(R.id.photo_touch_intercept_overlay);
}
public void setListener(Listener listener) {
mListener = listener;
}
public void setReadOnly(boolean readOnly) {
mReadOnly = readOnly;
if (mReadOnly) {
mPhotoIcon.setVisibility(View.GONE);
mPhotoIconOverlay.setVisibility(View.GONE);
mPhotoTouchInterceptOverlay.setClickable(false);
mPhotoTouchInterceptOverlay.setContentDescription(getContext().getString(
R.string.editor_contact_photo_content_description));
} else {
mPhotoIcon.setVisibility(View.VISIBLE);
mPhotoIconOverlay.setVisibility(View.VISIBLE);
mPhotoTouchInterceptOverlay.setOnClickListener(this);
updatePhotoDescription();
}
}
public void setPalette(MaterialPalette palette) {
mMaterialPalette = palette;
}
/**
* Tries to bind a full size photo or a bitmap loaded from the given ValuesDelta,
* and falls back to the default avatar, tinted using the given MaterialPalette (if it's not
* null);
*/
public void setPhoto(ValuesDelta valuesDelta) {
// Check if we can update to the full size photo immediately
final Long photoFileId = EditorUiUtils.getPhotoFileId(valuesDelta);
if (photoFileId != null) {
final Uri photoUri = ContactsContract.DisplayPhoto.CONTENT_URI.buildUpon()
.appendPath(photoFileId.toString()).build();
setFullSizedPhoto(photoUri);
adjustDimensions();
return;
}
// Use the bitmap image from the values delta
final Bitmap bitmap = EditorUiUtils.getPhotoBitmap(valuesDelta);
if (bitmap != null) {
setPhoto(bitmap);
adjustDimensions();
return;
}
setDefaultPhoto(mMaterialPalette);
adjustDimensions();
}
private void adjustDimensions() {
// Follow the same logic as MultiShrinkScroll.initialize
SchedulingUtils.doOnPreDraw(this, /* drawNextFrame =*/ false, new Runnable() {
@Override
public void run() {
final int photoHeight, photoWidth;
if (mIsTwoPanel) {
photoHeight = getHeight();
photoWidth = (int) (photoHeight * mLandscapePhotoRatio);
} else {
// Make the photo slightly shorter that it is wide
photoWidth = getWidth();
photoHeight = (int) (photoWidth / mPortraitPhotoRatio);
}
final ViewGroup.LayoutParams layoutParams = getLayoutParams();
layoutParams.height = photoHeight;
layoutParams.width = photoWidth;
setLayoutParams(layoutParams);
}
});
}
/**
* Whether a removable, non-default photo is bound to this view.
*/
public boolean isWritablePhotoSet() {
return !mReadOnly && mIsNonDefaultPhotoBound;
}
/**
* Binds the given bitmap.
*/
private void setPhoto(Bitmap bitmap) {
mPhotoImageView.setImageBitmap(bitmap);
mIsNonDefaultPhotoBound = true;
updatePhotoDescription();
}
private void setDefaultPhoto(MaterialPalette materialPalette) {
mIsNonDefaultPhotoBound = false;
updatePhotoDescription();
EditorUiUtils.setDefaultPhoto(mPhotoImageView, getResources(), materialPalette);
}
private void updatePhotoDescription() {
mPhotoTouchInterceptOverlay.setContentDescription(getContext().getString(
mIsNonDefaultPhotoBound
? R.string.editor_change_photo_content_description
: R.string.editor_add_photo_content_description));
}
/**
* Binds a full size photo loaded from the given Uri.
*/
public void setFullSizedPhoto(Uri photoUri) {
mPhotoImageView.setImageURI(photoUri);
mIsNonDefaultPhotoBound = true;
updatePhotoDescription();
}
/**
* Removes the current bound photo bitmap.
*/
public void removePhoto() {
setDefaultPhoto(mMaterialPalette);
}
@Override
public void onClick(View view) {
if (mListener != null) {
mListener.onPhotoEditorViewClicked();
}
}
}