/*
* Copyright 2012 Google Inc. All Rights Reserved.
*
* 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.examples.youtubeapidemo.ui;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* A view which displays a grid of images.
*/
public class ImageWallView extends ViewGroup {
private final Context context;
private final Random random;
private final int imageHeight;
private final int imageWidth;
private final int interImagePadding;
private ImageView[] images;
private List<Integer> unInitializedImages;
private int numberOfColumns;
private int numberOfRows;
public ImageWallView(Context context, int imageWidth, int imageHeight, int interImagePadding) {
super(context);
this.context = context;
random = new Random();
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
this.interImagePadding = interImagePadding;
this.images = new ImageView[0];
this.unInitializedImages = new ArrayList<Integer>();
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
// create enough columns to fill view's width, plus an extra column at either side to allow
// images to have diagonal offset across the screen.
numberOfColumns = width / (imageWidth + interImagePadding) + 2;
// create enough rows to fill the view's height (adding an extra row at bottom if necessary).
numberOfRows = height / (imageHeight + interImagePadding);
numberOfRows += (height % (imageHeight + interImagePadding) == 0) ? 0 : 1;
if ((numberOfRows <= 0) || (numberOfColumns <= 0)) {
throw new IllegalStateException("Error creating an ImageWallView with " + numberOfRows
+ " rows and " + numberOfColumns + " columns. Both values must be greater than zero.");
}
if (images.length < (numberOfColumns * numberOfRows)) {
images = Arrays.copyOf(images, numberOfColumns * numberOfRows);
}
removeAllViews();
for (int col = 0; col < numberOfColumns; col++) {
for (int row = 0; row < numberOfRows; row++) {
int elementIdx = getElementIdx(col, row);
if (images[elementIdx] == null) {
ImageView thumbnail = new ImageView(context);
thumbnail.setLayoutParams(new LayoutParams(imageWidth, imageHeight));
images[elementIdx] = thumbnail;
unInitializedImages.add(elementIdx);
}
addView(images[elementIdx]);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int width = getDefaultSize(displayMetrics.widthPixels, widthMeasureSpec);
int height = getDefaultSize(displayMetrics.heightPixels, heightMeasureSpec);
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
for (int col = 0; col < numberOfColumns; col++) {
for (int row = 0; row < numberOfRows; row++) {
int x = (col - 1) * (imageWidth + interImagePadding) + (row * (imageWidth / numberOfRows));
int y = row * (imageHeight + interImagePadding);
images[col * numberOfRows + row].layout(x, y, x + imageWidth, y + imageHeight);
}
}
}
public int getXPosition(int col, int row) {
return images[getElementIdx(col, row)].getLeft();
}
public int getYPosition(int col, int row) {
return images[getElementIdx(col, row)].getTop();
}
private int getElementIdx(int col, int row) {
return (col * numberOfRows) + row;
}
public void hideImage(int col, int row) {
images[getElementIdx(col, row)].setVisibility(View.INVISIBLE);
}
public void showImage(int col, int row) {
images[getElementIdx(col, row)].setVisibility(View.VISIBLE);
}
public void setImageDrawable(int col, int row, Drawable drawable) {
int elementIdx = getElementIdx(col, row);
// manually boxing elementIdx to avoid calling List.remove(int position) method overload
unInitializedImages.remove(new Integer(elementIdx));
images[elementIdx].setImageDrawable(drawable);
}
public Drawable getImageDrawable(int col, int row) {
int elementIdx = getElementIdx(col, row);
return images[elementIdx].getDrawable();
}
public Pair<Integer, Integer> getNextLoadTarget() {
int nextElement;
do {
if (unInitializedImages.isEmpty()) {
// Don't choose the first or last columns (since they are partly hidden)
nextElement = random.nextInt((numberOfColumns - 2) * numberOfRows) + numberOfRows;
} else {
nextElement = unInitializedImages.get(random.nextInt(unInitializedImages.size()));
}
} while (images[nextElement].getVisibility() != View.VISIBLE);
int col = nextElement / numberOfRows;
int row = nextElement % numberOfRows;
return new Pair<Integer, Integer>(col, row);
}
public boolean allImagesLoaded() {
return unInitializedImages.isEmpty();
}
}