1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.ui.mediapicker; 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context; 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.Cursor; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.Rect; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.util.AttributeSet; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.MotionEvent; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.TouchDelegate; 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.View; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.CheckBox; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.FrameLayout; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.ImageView.ScaleType; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.R; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.GalleryGridItemData; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.AsyncImageView; 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.ConversationDrawables; 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.annotations.VisibleForTesting; 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.concurrent.TimeUnit; 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Shows an item in the gallery picker grid view. Hosts an FileImageView with a checkbox. 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class GalleryGridItemView extends FrameLayout { 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Implemented by the owner of this GalleryGridItemView instance to communicate on media 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * picking and selection events. 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public interface HostInterface { 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd void onItemClicked(View view, GalleryGridItemData data, boolean longClick); 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean isItemSelected(GalleryGridItemData data); 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean isMultiSelectEnabled(); 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @VisibleForTesting 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd GalleryGridItemData mData; 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private AsyncImageView mImageView; 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private CheckBox mCheckBox; 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private HostInterface mHostInterface; 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private final OnClickListener mOnClickListener = new OnClickListener() { 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void onClick(final View v) { 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mHostInterface.onItemClicked(GalleryGridItemView.this, mData, false /*longClick*/); 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public GalleryGridItemView(final Context context, final AttributeSet attrs) { 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super(context, attrs); 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData = DataModel.get().createGalleryGridItemData(); 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected void onFinishInflate() { 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super.onFinishInflate(); 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mImageView = (AsyncImageView) findViewById(R.id.image); 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCheckBox = (CheckBox) findViewById(R.id.checkbox); 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCheckBox.setOnClickListener(mOnClickListener); 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setOnClickListener(mOnClickListener); 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final OnLongClickListener longClickListener = new OnLongClickListener() { 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean onLongClick(final View v) { 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mHostInterface.onItemClicked(v, mData, true /* longClick */); 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setOnLongClickListener(longClickListener); 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCheckBox.setOnLongClickListener(longClickListener); 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd addOnLayoutChangeListener(new OnLayoutChangeListener() { 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void onLayoutChange(View v, int left, int top, int right, int bottom, 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int oldLeft, int oldTop, int oldRight, int oldBottom) { 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Enlarge the clickable region for the checkbox to fill the entire view. 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Rect region = new Rect(0, 0, getWidth(), getHeight()); 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setTouchDelegate(new TouchDelegate(region, mCheckBox) { 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean onTouchEvent(MotionEvent event) { 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd switch (event.getAction()) { 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MotionEvent.ACTION_DOWN: 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setPressed(true); 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MotionEvent.ACTION_UP: 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MotionEvent.ACTION_CANCEL: 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setPressed(false); 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return super.onTouchEvent(event); 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }); 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }); 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // The grid view auto-fit the columns, so we want to let the height match the width 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // to make the image square. 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super.onMeasure(widthMeasureSpec, widthMeasureSpec); 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void bind(final Cursor cursor, final HostInterface hostInterface) { 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int desiredSize = getResources() 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getDimensionPixelSize(R.dimen.gallery_image_cell_size); 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.bind(cursor, desiredSize, desiredSize); 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mHostInterface = hostInterface; 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateViewState(); 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateViewState() { 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateImageView(); 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mHostInterface.isMultiSelectEnabled() && !mData.isDocumentPickerItem()) { 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCheckBox.setVisibility(VISIBLE); 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCheckBox.setClickable(true); 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCheckBox.setChecked(mHostInterface.isItemSelected(mData)); 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCheckBox.setVisibility(GONE); 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCheckBox.setClickable(false); 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateImageView() { 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mData.isDocumentPickerItem()) { 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mImageView.setScaleType(ScaleType.CENTER); 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setBackgroundColor(ConversationDrawables.get().getConversationThemeColor()); 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mImageView.setImageResourceId(null); 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mImageView.setImageResource(R.drawable.ic_photo_library_light); 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mImageView.setContentDescription(getResources().getString( 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.string.pick_image_from_document_library_content_description)); 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mImageView.setScaleType(ScaleType.CENTER_CROP); 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setBackgroundColor(getResources().getColor(R.color.gallery_image_default_background)); 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mImageView.setImageResourceId(mData.getImageRequestDescriptor()); 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long dateSeconds = mData.getDateSeconds(); 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isValidDate = (dateSeconds > 0); 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int templateId = isValidDate ? 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.string.mediapicker_gallery_image_item_description : 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.string.mediapicker_gallery_image_item_description_no_date; 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String contentDescription = String.format(getResources().getString(templateId), 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd dateSeconds * TimeUnit.SECONDS.toMillis(1)); 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mImageView.setContentDescription(contentDescription); 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 160