diff options
Diffstat (limited to 'libraries/StickyListHeaders/library/src/se/emilsjolander/stickylistheaders/AdapterWrapper.java')
-rw-r--r-- | libraries/StickyListHeaders/library/src/se/emilsjolander/stickylistheaders/AdapterWrapper.java | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/libraries/StickyListHeaders/library/src/se/emilsjolander/stickylistheaders/AdapterWrapper.java b/libraries/StickyListHeaders/library/src/se/emilsjolander/stickylistheaders/AdapterWrapper.java new file mode 100644 index 000000000..e67de0dbf --- /dev/null +++ b/libraries/StickyListHeaders/library/src/se/emilsjolander/stickylistheaders/AdapterWrapper.java @@ -0,0 +1,225 @@ +package se.emilsjolander.stickylistheaders; + +import java.util.LinkedList; +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.Checkable; +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) + */ +class AdapterWrapper extends BaseAdapter implements StickyListHeadersAdapter { + + interface OnHeaderClickListener { + public void onHeaderClick(View header, int itemPosition, long headerId); + } + + final StickyListHeadersAdapter mDelegate; + private final List<View> mHeaderCache = new LinkedList<View>(); + private final Context mContext; + private Drawable mDivider; + private int mDividerHeight; + private OnHeaderClickListener mOnHeaderClickListener; + private DataSetObserver mDataSetObserver = new DataSetObserver() { + + @Override + public void onInvalidated() { + mHeaderCache.clear(); + AdapterWrapper.super.notifyDataSetInvalidated(); + } + + @Override + public void onChanged() { + AdapterWrapper.super.notifyDataSetChanged(); + } + }; + + AdapterWrapper(Context context, + StickyListHeadersAdapter delegate) { + this.mContext = context; + this.mDelegate = delegate; + delegate.registerDataSetObserver(mDataSetObserver); + } + + void setDivider(Drawable divider, int dividerHeight) { + this.mDivider = divider; + this.mDividerHeight = dividerHeight; + notifyDataSetChanged(); + } + + @Override + public boolean areAllItemsEnabled() { + return mDelegate.areAllItemsEnabled(); + } + + @Override + public boolean isEnabled(int position) { + return mDelegate.isEnabled(position); + } + + @Override + public int getCount() { + return mDelegate.getCount(); + } + + @Override + public Object getItem(int position) { + return mDelegate.getItem(position); + } + + @Override + public long getItemId(int position) { + return mDelegate.getItemId(position); + } + + @Override + public boolean hasStableIds() { + return mDelegate.hasStableIds(); + } + + @Override + public int getItemViewType(int position) { + return mDelegate.getItemViewType(position); + } + + @Override + public int getViewTypeCount() { + return mDelegate.getViewTypeCount(); + } + + @Override + public boolean isEmpty() { + return mDelegate.isEmpty(); + } + + /** + * Will recycle header from {@link WrapperView} if it exists + */ + private void recycleHeaderIfExists(WrapperView wv) { + View header = wv.mHeader; + if (header != null) { + // reset the headers visibility when adding it to the cache + header.setVisibility(View.VISIBLE); + mHeaderCache.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.mHeader == null ? popHeader() : wv.mHeader; + header = mDelegate.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(mOnHeaderClickListener != null){ + long headerId = mDelegate.getHeaderId(position); + mOnHeaderClickListener.onHeaderClick(v, position, headerId); + } + } + }); + return header; + } + + private View popHeader() { + if(mHeaderCache.size() > 0) { + return mHeaderCache.remove(0); + } + return null; + } + + /** Returns {@code true} if the previous position has the same header ID. */ + private boolean previousPositionHasSameHeader(int position) { + return position != 0 + && mDelegate.getHeaderId(position) == mDelegate + .getHeaderId(position - 1); + } + + @Override + public WrapperView getView(int position, View convertView, ViewGroup parent) { + WrapperView wv = (convertView == null) ? new WrapperView(mContext) : (WrapperView) convertView; + View item = mDelegate.getView(position, wv.mItem, parent); + View header = null; + if (previousPositionHasSameHeader(position)) { + recycleHeaderIfExists(wv); + } else { + header = configureHeader(wv, position); + } + if((item instanceof Checkable) && !(wv instanceof CheckableWrapperView)) { + // Need to create Checkable subclass of WrapperView for ListView to work correctly + wv = new CheckableWrapperView(mContext); + } else if(!(item instanceof Checkable) && (wv instanceof CheckableWrapperView)) { + wv = new WrapperView(mContext); + } + wv.update(item, header, mDivider, mDividerHeight); + return wv; + } + + public void setOnHeaderClickListener(OnHeaderClickListener onHeaderClickListener){ + this.mOnHeaderClickListener = onHeaderClickListener; + } + + @Override + public boolean equals(Object o) { + return mDelegate.equals(o); + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + return ((BaseAdapter) mDelegate).getDropDownView(position, convertView, parent); + } + + @Override + public int hashCode() { + return mDelegate.hashCode(); + } + + @Override + public void notifyDataSetChanged() { + ((BaseAdapter) mDelegate).notifyDataSetChanged(); + } + + @Override + public void notifyDataSetInvalidated() { + ((BaseAdapter) mDelegate).notifyDataSetInvalidated(); + } + + @Override + public String toString() { + return mDelegate.toString(); + } + + @Override + public View getHeaderView(int position, View convertView, ViewGroup parent) { + return mDelegate.getHeaderView(position, convertView, parent); + } + + @Override + public long getHeaderId(int position) { + return mDelegate.getHeaderId(position); + } + +} |