package com.emilsjolander.components.stickylistheaders;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
/**
* A {@link ListAdapter} which wraps a {@link StickyListHeadersAdapter} and
* automatically handles wrapping the result of
* {@link StickyListHeadersAdapter#getView(int, android.view.View, android.view.ViewGroup)}
* and
* {@link StickyListHeadersAdapter#getHeaderView(int, android.view.View, android.view.ViewGroup)}
* appropriately.
*
* @author Jake Wharton (jakewharton@gmail.com)
*/
final class StickyListHeadersAdapterWrapper extends BaseAdapter {
public interface OnHeaderClickListener{
public void onHeaderClick(View header, int itemPosition, long headerId);
}
private final List<View> headerCache = new ArrayList<View>();
private final Context context;
final StickyListHeadersAdapter delegate;
private Drawable divider;
private int dividerHeight;
private DataSetObserver dataSetObserver = new DataSetObserver() {
@Override
public void onInvalidated() {
headerCache.clear();
}
};
private OnHeaderClickListener onHeaderClickListener;
StickyListHeadersAdapterWrapper(Context context,
StickyListHeadersAdapter delegate) {
this.context = context;
this.delegate = delegate;
delegate.registerDataSetObserver(dataSetObserver);
}
void setDivider(Drawable divider) {
this.divider = divider;
}
void setDividerHeight(int dividerHeight) {
this.dividerHeight = dividerHeight;
}
@Override
public boolean areAllItemsEnabled() {
return delegate.areAllItemsEnabled();
}
@Override
public boolean isEnabled(int position) {
return delegate.isEnabled(position);
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
delegate.registerDataSetObserver(observer);
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
delegate.unregisterDataSetObserver(observer);
}
@Override
public int getCount() {
return delegate.getCount();
}
@Override
public Object getItem(int position) {
return delegate.getItem(position);
}
@Override
public long getItemId(int position) {
return delegate.getItemId(position);
}
@Override
public boolean hasStableIds() {
return delegate.hasStableIds();
}
@Override
public int getItemViewType(int position) {
return delegate.getItemViewType(position);
}
@Override
public int getViewTypeCount() {
return delegate.getViewTypeCount();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
/**
* Will recycle header from {@link WrapperView} if it exists
*/
private void recycleHeaderIfExists(WrapperView wv) {
View header = wv.header;
if (header != null) {
headerCache.add(header);
}
}
/**
* Get a header view. This optionally pulls a header from the supplied
* {@link WrapperView} and will also recycle the divider if it exists.
*/
private View configureHeader(WrapperView wv, final int position) {
View header = wv.header;
header = delegate.getHeaderView(position, header, wv);
if (header == null) {
throw new NullPointerException("Header view must not be null.");
}
//if the header isn't clickable, the listselector will be drawn on top of the header
header.setClickable(true);
header.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(onHeaderClickListener != null){
long headerId = delegate.getHeaderId(position);
onHeaderClickListener.onHeaderClick(v, position, headerId);
}
}
});
return header;
}
/** Returns {@code true} if the previous position has the same header ID. */
private boolean previousPositionHasSameHeader(int position) {
return position != 0
&& delegate.getHeaderId(position) == delegate
.getHeaderId(position - 1);
}
@Override
public WrapperView getView(int position, View convertView, ViewGroup parent) {
WrapperView wv = (convertView == null) ? new WrapperView(context)
: (WrapperView) convertView;
View item = delegate.getView(position, wv.item, wv);
View header = null;
if (previousPositionHasSameHeader(position)) {
recycleHeaderIfExists(wv);
} else {
header = configureHeader(wv, position);
}
wv.update(item, header, divider, dividerHeight);
return wv;
}
public void setOnHeaderClickListener(OnHeaderClickListener onHeaderClickListener){
this.onHeaderClickListener = onHeaderClickListener;
}
}