package pl.polidea.androidflip3d; import java.util.ArrayList; import java.util.Collections; import java.util.List; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView.RecyclerListener; import android.widget.BaseAdapter; import android.widget.GridView; /** * Adapter for Flip Images displayed in Grid. Works around a nasty (really * nasty!) Android problem with many calls to the same item in a grid. * * @param <State> * state where information about view state are stored * @param <FlipView> * the view itself * */ public abstract class AbstractGridFlip3DImageAdapter<State extends Flip3DViewState, FlipView extends Flip3DView> extends BaseAdapter implements RecyclerListener { static final int MAX_IMAGES = 20; private final List<State> viewStates = new ArrayList<State>(MAX_IMAGES); private final int itemWidth; public AbstractGridFlip3DImageAdapter(final int itemWidth) { super(); this.itemWidth = itemWidth; } public synchronized void setViewStates(final List<State> statesToSet) { viewStates.clear(); for (final State state : statesToSet) { viewStates.add(state); } notifyDataSetChanged(); } @Override public int getCount() { return viewStates.size(); } @Override public Object getItem(final int position) { // NOPMD return null; } @Override public long getItemId(final int position) { // NOPMD return 0; } @SuppressWarnings("unchecked") @Override public synchronized View getView(final int position, final View convertView, final ViewGroup parent) { if (checkifExtraCall(position, convertView)) { // DIRTY HACK ... BUT // THIS IS THE ONLY WAY // WITH GRID VIEW return convertView == null ? createView() : convertView; } FlipView newView; if (convertView == null) { newView = createView(); } else { newView = (FlipView) convertView; } prepareView(position, newView); newView.setLayoutParams(new GridView.LayoutParams(itemWidth, itemWidth)); return newView; } public synchronized List<State> getViewStates() { return Collections.unmodifiableList(viewStates); } protected abstract FlipView createView(); protected abstract void prepareView(int position, FlipView view); private boolean checkifExtraCall(final int position, final View convertView) { // XXX: HACK. Grid view uses multiple calls to first item in order // to calculate size of the grid!!! // Which is really a hack as I see (but not some android // developers!): // http://www.mail-archive.com/android-developers@googlegroups.com/msg57716.html if (position == 0 && convertView != null && convertView.getId() == 0) { return true; } State viewState = null; if (position >= 0 && position < viewStates.size()) { viewState = viewStates.get(position); if (viewState != null && viewState.getView() != null) { return position == 0; } } return false; } @Override public synchronized void onMovedToScrapHeap(final View view) { for (final Flip3DViewState s : viewStates) { s.detachView((Flip3DView) view); } } }