package com.meg7.soas.ui.adapter; import android.content.Context; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.android.volley.toolbox.ImageLoader; import com.meg7.soas.R; import com.meg7.soas.SoasApplication; import java.util.Collection; import java.util.List; /** * A child class shall subclass this Adapter and * implement method getDataRow(int position, View convertView, ViewGroup parent), * which supplies a View present data in a ListRow. * <p/> * This parent Adapter takes care of displaying ProgressBar in a row or * indicating that it has reached the last row. */ // Based on https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews public abstract class BaseEndlessAdapter<T> extends BaseAdapter { protected Context mContext; protected final LayoutInflater mInflater; protected final ImageLoader mImageLoader; /** * The main data list to save loaded data. */ protected List<T> mItems; /** * Lock used to modify the content of {@link #mItems}. Any write operation * performed on the array should be synchronized on this lock. */ private final Object mLock = new Object(); // The serverListSize is the total number of items on the server side, // which should be returned from the web request results. protected int mServerListSize = -1; // Two view types which will be used to determine whether a row should be displaying // data or a Progressbar. public static final int VIEW_TYPE_LOADING = 0; public static final int VIEW_TYPE_ACTIVITY = 1; public BaseEndlessAdapter(Context context, List<T> list, int serverListSize) { mContext = context; mItems = list; mServerListSize = serverListSize; mInflater = LayoutInflater.from(context); mImageLoader = SoasApplication.getImageLoader(context); } public void setServerListSize(int serverListSize) { mServerListSize = serverListSize; } /** * Disable click events on indicating rows. * * @param position Index of the item. * @return True if the item is not a separator. */ @Override public boolean isEnabled(int position) { return getItemViewType(position) == VIEW_TYPE_ACTIVITY; } /** * One type is normal data row, the other type is ProgressBar. * * @return The number of types of Views that will be created by this adapter. */ @Override public int getViewTypeCount() { return 2; } /** * The size of the List plus one, the one is the last row, which displays a Progressbar. * * @return The size of the List plus one for the ProgressBar. */ @Override public int getCount() { return mItems.size() + 1; } /** * Return the type of the row, * the last row indicates the user that the ListView is loading more data. * * @return Row type. */ @Override public int getItemViewType(int position) { return (position >= mItems.size()) ? VIEW_TYPE_LOADING : VIEW_TYPE_ACTIVITY; } @Override public T getItem(int position) { return (getItemViewType(position) == VIEW_TYPE_ACTIVITY) ? mItems .get(position) : null; } @Override public long getItemId(int position) { return (getItemViewType(position) == VIEW_TYPE_ACTIVITY) ? position : -1; } /** * Returns the correct view. */ @Override public View getView(int position, View convertView, ViewGroup parent) { if (getItemViewType(position) == VIEW_TYPE_LOADING) { // display the last row return getFooterView(position, convertView, parent); } View dataRow = convertView; dataRow = getDataRow(position, convertView, parent); return dataRow; } /** * A subclass should override this method to supply the data row. */ public abstract View getDataRow(int position, View convertView, ViewGroup parent); /** * Returns a View to be displayed in the last row. */ public View getFooterView(int position, View convertView, ViewGroup parent) { if (position >= mServerListSize && mServerListSize > 0) { // The ListView has reached the last row. TextView tvLastRow = new TextView(mContext); tvLastRow.setHint(R.string.list_last_row_reached); tvLastRow.setGravity(Gravity.CENTER); return tvLastRow; } View row = convertView; if (row == null) { row = LayoutInflater.from(mContext).inflate( R.layout.list_footer_progress, parent, false); } return row; } /** * Adds the specified Collection at the end of the array. * * @param collection The Collection to add at the end of the array. */ public void addAll(Collection<? extends T> collection) { synchronized (mLock) { mItems.addAll(collection); } notifyDataSetChanged(); } /** * Remove all elements from the list. */ public void clear() { synchronized (mLock) { mItems.clear(); } notifyDataSetChanged(); } }