package com.aincc.lib.ui.widget.list.section;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.SectionIndexer;
/**
*
* <h3><b>AmazingAdapter</b></h3></br>
*
* @author aincc@barusoft.com
* @version 1.0.0
* @since 1.0.0
*/
public abstract class AmazingAdapter extends BaseAdapter implements SectionIndexer, OnScrollListener
{
public static final String TAG = AmazingAdapter.class.getSimpleName();
public interface HasMorePagesListener
{
void noMorePages();
void mayHaveMorePages();
}
/**
* The <em>current</em> page, not the page that is going to be loaded.
*/
int page = 1;
int initialPage = 1;
boolean automaticNextPageLoading = false;
HasMorePagesListener hasMorePagesListener;
void setHasMorePagesListener(HasMorePagesListener hasMorePagesListener)
{
this.hasMorePagesListener = hasMorePagesListener;
}
/**
* Pinned header state: don't show the header.
*/
public static final int PINNED_HEADER_GONE = 0;
/**
* Pinned header state: show the header at the top of the list.
*/
public static final int PINNED_HEADER_VISIBLE = 1;
/**
* Pinned header state: show the header. If the header extends beyond
* the bottom of the first shown element, push it up and clip.
*/
public static final int PINNED_HEADER_PUSHED_UP = 2;
/**
* Computes the desired state of the pinned header for the given
* position of the first visible list item. Allowed return values are {@link #PINNED_HEADER_GONE}, {@link #PINNED_HEADER_VISIBLE} or {@link #PINNED_HEADER_PUSHED_UP}.
*/
public int getPinnedHeaderState(int position)
{
if (position < 0 || getCount() == 0)
{
return PINNED_HEADER_GONE;
}
// The header should get pushed up if the top item shown
// is the last item in a section for a particular letter.
int section = getSectionForPosition(position);
int nextSectionPosition = getPositionForSection(section + 1);
if (nextSectionPosition != -1 && position == nextSectionPosition - 1)
{
return PINNED_HEADER_PUSHED_UP;
}
return PINNED_HEADER_VISIBLE;
}
/**
* Sets the initial page when {@link #resetPage()} is called.
* Default is 1 (for APIs with 1-based page number).
*/
public void setInitialPage(int initialPage)
{
this.initialPage = initialPage;
}
/**
* Resets the current page to the page specified in {@link #setInitialPage(int)}.
*/
public void resetPage()
{
this.page = this.initialPage;
}
/**
* Increases the current page number.
*/
public void nextPage()
{
this.page++;
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
if (view instanceof AmazingListView)
{
((AmazingListView) view).configureHeaderView(firstVisibleItem);
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
// nop
}
@Override
public final View getView(int position, View convertView, ViewGroup parent)
{
View res = getAmazingView(position, convertView, parent);
if (position == getCount() - 1 && automaticNextPageLoading)
{
onNextPageRequested(page + 1);
}
final int section = getSectionForPosition(position);
boolean displaySectionHeaders = (getPositionForSection(section) == position);
bindSectionHeader(res, position, displaySectionHeaders);
return res;
}
public void notifyNoMorePages()
{
automaticNextPageLoading = false;
if (hasMorePagesListener != null)
hasMorePagesListener.noMorePages();
}
public void notifyMayHaveMorePages()
{
automaticNextPageLoading = true;
if (hasMorePagesListener != null)
hasMorePagesListener.mayHaveMorePages();
}
/**
* The last item on the list is requested to be seen, so do the request
* and call {@link AmazingListView#tellNoMoreData()} if there is no more pages.
*
* @param page
* the page number to load.
*/
protected abstract void onNextPageRequested(int page);
/**
* Configure the view (a listview item) to display headers or not based on displaySectionHeader
* (e.g. if displaySectionHeader header.setVisibility(VISIBLE) else header.setVisibility(GONE)).
*/
protected abstract void bindSectionHeader(View view, int position, boolean displaySectionHeader);
/**
* read: get view too
*/
public abstract View getAmazingView(int position, View convertView, ViewGroup parent);
/**
* Configures the pinned header view to match the first visible list item.
*
* @param header
* pinned header view.
* @param position
* position of the first visible list item.
* @param alpha
* fading of the header view, between 0 and 255.
*/
public abstract void configurePinnedHeader(View header, int position, int alpha);
@Override
public abstract int getPositionForSection(int section);
@Override
public abstract int getSectionForPosition(int position);
@Override
public abstract Object[] getSections();
}