@Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final int maxWidth = getResources().getDimensionPixelSize(R.dimen.multiple_attachment_preview_width); final int maxHeight = getResources().getDimensionPixelSize(R.dimen.multiple_attachment_preview_height); final int width = Math.min(MeasureSpec.getSize(widthMeasureSpec), maxWidth); final int height = maxHeight; final int cellWidth = width / GRID_WIDTH; final int cellHeight = height / GRID_HEIGHT; final int count = mPreviewViews.size(); final int padding = getResources().getDimensionPixelOffset(R.dimen.multiple_attachment_preview_padding); for (int i = 0; i < count; i++) { final View view = mPreviewViews.get(i).view; final Tile imageTile = mCurrentLayout.tiles.get(i); view.measure( imageTile.getWidthMeasureSpec(cellWidth, padding), imageTile.getHeightMeasureSpec(cellHeight, padding)); // Now that we know the size, we can request an appropriately-sized image. if (view instanceof AsyncImageView) { final ImageRequestDescriptor imageRequest = AttachmentPreviewFactory.getImageRequestDescriptorForAttachment( mPreviewViews.get(i).attachment, view.getMeasuredWidth(), view.getMeasuredHeight()); ((AsyncImageView) view).setImageResourceId(imageRequest); } if (i == count - 1 && mPlusTextView != null) { // The plus text view always covers the last attachment. mPlusTextView.measure( imageTile.getWidthMeasureSpec(cellWidth, padding), imageTile.getHeightMeasureSpec(cellHeight, padding)); } } setMeasuredDimension(width, height); }
private void buildViews( final Iterable<MessagePartData> attachments, final ArrayList<ViewWrapper> previousViews, final Rect transitionRect) { final LayoutInflater layoutInflater = LayoutInflater.from(getContext()); final int count = mCurrentLayout.tiles.size(); int i = 0; final Iterator<MessagePartData> iterator = attachments.iterator(); while (iterator.hasNext() && i < count) { final MessagePartData attachment = iterator.next(); ViewWrapper attachmentWrapper = null; // Try to recycle a previous view first for (int j = 0; j < previousViews.size(); j++) { final ViewWrapper previousView = previousViews.get(j); if (previousView.attachment.equals(attachment) && !(previousView.attachment instanceof PendingAttachmentData)) { attachmentWrapper = previousView; previousViews.remove(j); break; } } if (attachmentWrapper == null) { final View view = AttachmentPreviewFactory.createAttachmentPreview( layoutInflater, attachment, this, AttachmentPreviewFactory.TYPE_MULTIPLE, false /* startImageRequest */, mAttachmentClickListener); if (view == null) { // createAttachmentPreview can return null if something goes wrong (e.g. // attachment has unsupported contentType) continue; } if (view instanceof AsyncImageView && mImageViewDelayLoader != null) { AsyncImageView asyncImageView = (AsyncImageView) view; asyncImageView.setDelayLoader(mImageViewDelayLoader); } addView(view); attachmentWrapper = new ViewWrapper(view, attachment); // Help animate from single to multi by copying over the prev location if (count == 2 && i == 1 && transitionRect != null) { attachmentWrapper.prevLeft = transitionRect.left; attachmentWrapper.prevTop = transitionRect.top; attachmentWrapper.prevWidth = transitionRect.width(); attachmentWrapper.prevHeight = transitionRect.height(); } } i++; Assert.notNull(attachmentWrapper); mPreviewViews.add(attachmentWrapper); // The first view will animate in using PopupTransitionAnimation, but the remaining // views will slide from their previous position to their new position within the // layout if (i == 0) { AttachmentPreview.tryAnimateViewIn(attachment, attachmentWrapper.view); } attachmentWrapper.needsSlideAnimation = i > 0; } // Build the plus text view (e.g. "+2") for when there are more attachments than what // this layout can display. if (mPlusNumber > 0) { mPlusTextView = (TextView) layoutInflater.inflate(R.layout.attachment_more_text_view, null /* parent */); mPlusTextView.setText(getResources().getString(R.string.attachment_more_items, mPlusNumber)); addView(mPlusTextView); } }