package com.paging.gridview; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.GridView; import android.widget.ListAdapter; import java.util.ArrayList; public class HeaderGridView extends GridView { private ListAdapter mAdapter; private Context mContext; /** * Should be used by subclasses to listen to changes in the dataset */ // AdapterDataSetObserver mDataSetObserver; public HeaderGridView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } public HeaderGridView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public HeaderGridView(Context context) { super(context); init(context); } private void init(Context context){ mContext = context; // super.setOnScrollListener(this); } /** * A class that represents a fixed view in a list, for example a header at the top * or a footer at the bottom. */ private ArrayList<FixedViewInfo> mHeaderViewInfos = new ArrayList<FixedViewInfo>(); private ArrayList<FixedViewInfo> mFooterViewInfos = new ArrayList<FixedViewInfo>(); private void notifiyChanged(){ this.requestLayout(); this.invalidate(); } /** * Add a fixed view to appear at the top of the list. If this method is * called more than once, the views will appear in the order they were * added. Views added using this call can take focus if they want. * <p> * Note: When first introduced, this method could only be called before * setting the adapter with {@link #setAdapter(ListAdapter)}. Starting with * {@link android.os.Build.VERSION_CODES#KITKAT}, this method may be * called at any time. If the ListView's adapter does not extend * {@link FooterViewGridAdapter}, it will be wrapped with a supporting * instance of {@link android.widget.WrapperListAdapter}. * * @param v The view to add. * @param data Data to associate with this view * @param isSelectable whether the item is selectable */ public void addHeaderView(View v, Object data, boolean isSelectable) { final FixedViewInfo info = new FixedViewInfo(); FrameLayout fl = new FullWidthFixedViewLayout(getContext()); fl.addView(v); info.view = v; info.viewContainer = fl; info.data = data; info.isSelectable = isSelectable; mHeaderViewInfos.add(info); // Wrap the adapter if it wasn't already wrapped. if (mAdapter != null) { if (!(mAdapter instanceof FooterViewGridAdapter)) { mAdapter = new FooterViewGridAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); } // Do not know if this really helps notifiyChanged(); } } /** * Add a fixed view to appear at the top of the list. If addHeaderView is * called more than once, the views will appear in the order they were * added. Views added using this call can take focus if they want. * <p> * Note: When first introduced, this method could only be called before * setting the adapter with {@link #setAdapter(ListAdapter)}. Starting with * {@link android.os.Build.VERSION_CODES#KITKAT}, this method may be * called at any time. If the ListView's adapter does not extend * {@link FooterViewGridAdapter}, it will be wrapped with a supporting * instance of {@link android.widget.WrapperListAdapter}. * * @param v The view to add. */ public void addHeaderView(View v) { addHeaderView(v, null, true); } public int getHeaderViewsCount() { return mHeaderViewInfos.size(); } /** * Add a fixed view to appear at the bottom of the list. If addFooterView is * called more than once, the views will appear in the order they were * added. Views added using this call can take focus if they want. * <p> * Note: When first introduced, this method could only be called before * setting the adapter with {@link #setAdapter(ListAdapter)}. Starting with * {@link android.os.Build.VERSION_CODES#KITKAT}, this method may be * called at any time. If the ListView's adapter does not extend * {@link FooterViewGridAdapter}, it will be wrapped with a supporting * instance of {@link android.widget.WrapperListAdapter}. * * @param v The view to add. * @param data Data to associate with this view * @param isSelectable true if the footer view can be selected */ public void addFooterView(View v, Object data, boolean isSelectable) { final FixedViewInfo info = new FixedViewInfo(); FrameLayout fl = new FullWidthFixedViewLayout(getContext()); fl.addView(v); info.view = v; info.viewContainer = fl; info.data = data; info.isSelectable = isSelectable; mFooterViewInfos.add(info); // Wrap the adapter if it wasn't already wrapped. if (mAdapter != null) { if (!(mAdapter instanceof FooterViewGridAdapter)) { mAdapter = new FooterViewGridAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); } // Do not know if this really helps notifiyChanged(); } } /** * Add a fixed view to appear at the bottom of the list. If addFooterView is * called more than once, the views will appear in the order they were * added. Views added using this call can take focus if they want. * <p> * Note: When first introduced, this method could only be called before * setting the adapter with {@link #setAdapter(ListAdapter)}. Starting with * {@link android.os.Build.VERSION_CODES#KITKAT}, this method may be * called at any time. If the ListView's adapter does not extend * {@link FooterViewGridAdapter}, it will be wrapped with a supporting * instance of {@link android.widget.WrapperListAdapter}. * * @param v The view to add. */ public void addFooterView(View v) { addFooterView(v, null, true); } public int getFooterViewsCount() { return mFooterViewInfos.size(); } /** * Removes a previously-added footer view. * * @param v The view to remove * @return * true if the view was removed, false if the view was not a footer view */ public boolean removeFooterView(View v) { if (mFooterViewInfos.size() > 0) { boolean result = false; if (mAdapter != null && ((FooterViewGridAdapter) mAdapter).removeFooter(v)) { notifiyChanged(); result = true; } removeFixedViewInfo(v, mFooterViewInfos); return result; } return false; } private void removeFixedViewInfo(View v, ArrayList<FixedViewInfo> where) { int len = where.size(); for (int i = 0; i < len; ++i) { FixedViewInfo info = where.get(i); if (info.view == v) { where.remove(i); break; } } } @Override public void setAdapter(ListAdapter adapter) { this.mAdapter = adapter; if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) { mAdapter = new FooterViewGridAdapter(mHeaderViewInfos, mFooterViewInfos, adapter); } else { mAdapter = adapter; } super.setAdapter(adapter); super.setAdapter(this.mAdapter); requestLayout(); } @Override public ListAdapter getAdapter() { return this.mAdapter; } public class FixedViewInfo { public android.view.View view; public ViewGroup viewContainer; public java.lang.Object data; public boolean isSelectable; } private class FullWidthFixedViewLayout extends FrameLayout { public FullWidthFixedViewLayout(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int targetWidth = HeaderGridView.this.getMeasuredWidth() - HeaderGridView.this.getPaddingLeft() - HeaderGridView.this.getPaddingRight(); widthMeasureSpec = MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.getMode(widthMeasureSpec)); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } }