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