首页 > 系统 > Android > 正文

Android GridView添加头部问题的解决

2019-10-22 18:12:45
字体:
来源:转载
供稿:网友

我们都知道ListView有addHeaderView和addFooterView两个方法。其中addHeaderView是添加头部布局,addFooterView是添加底部布局。但是GridView却没有这两个方法这个时候就需要重写GridView了。geogle官方给出了重写的HeaderGridView不知道为什么没有添加到官方api里面。代码如下:

public class HeaderGridView extends GridView {  private static final String TAG = "HeaderGridView";  /**   * A class that represents a fixed view in a list, for example a header at the top   * or a footer at the bottom.   */  private static class FixedViewInfo {    /** The view to add to the grid */    public View view;    public ViewGroup viewContainer;    /** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */    public Object data;    /** <code>true</code> if the fixed view should be selectable in the grid */    public boolean isSelectable;  }  private ArrayList<FixedViewInfo> mHeaderViewInfos = new ArrayList<FixedViewInfo>();  private void initHeaderGridView() {    super.setClipChildren(false);  }  public HeaderGridView(Context context) {    super(context);    initHeaderGridView();  }  public HeaderGridView(Context context, AttributeSet attrs) {    super(context, attrs);    initHeaderGridView();  }  public HeaderGridView(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);    initHeaderGridView();  }  @SuppressLint("NewApi")  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    ListAdapter adapter = getAdapter();    if (adapter != null && adapter instanceof HeaderViewGridAdapter) {      ((HeaderViewGridAdapter) adapter).setNumColumns(getNumColumns());    }  }  @Override  public void setClipChildren(boolean clipChildren) {    // Ignore, since the header rows depend on not being clipped  }  /**   * Add a fixed view to appear at the top of the grid. 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: Call this before calling setAdapter. This is so HeaderGridView can wrap   * the supplied cursor with one that will also account for header views.   *   * @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) {    ListAdapter adapter = getAdapter();    if (adapter != null && ! (adapter instanceof HeaderViewGridAdapter)) {      throw new IllegalStateException(          "Cannot add header view to grid -- setAdapter has already been called.");    }    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);    // in the case of re-adding a header view, or adding one later on,    // we need to notify the observer    if (adapter != null) {      ((HeaderViewGridAdapter) adapter).notifyDataSetChanged();    }  }  /**   * Add a fixed view to appear at the top of the grid. 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: Call this before calling setAdapter. This is so HeaderGridView can wrap   * the supplied cursor with one that will also account for header views.   *   * @param v The view to add.   */  public void addHeaderView(View v) {    addHeaderView(v, null, true);  }  public int getHeaderViewCount() {    return mHeaderViewInfos.size();  }  /**   * Removes a previously-added header view.   *   * @param v The view to remove   * @return true if the view was removed, false if the view was not a header   *     view   */  public boolean removeHeaderView(View v) {    if (mHeaderViewInfos.size() > 0) {      boolean result = false;      ListAdapter adapter = getAdapter();      if (adapter != null && ((HeaderViewGridAdapter) adapter).removeHeader(v)) {        result = true;      }      removeFixedViewInfo(v, mHeaderViewInfos);      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;      }    }  }  @SuppressLint("NewApi")  @Override  public void setAdapter(ListAdapter adapter) {    if (mHeaderViewInfos.size() > 0) {      HeaderViewGridAdapter hadapter = new HeaderViewGridAdapter(mHeaderViewInfos, adapter);      int numColumns = getNumColumns();      if (numColumns > 1) {        hadapter.setNumColumns(numColumns);      }      super.setAdapter(hadapter);    } else {      super.setAdapter(adapter);    }  }  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);    }  }  /**   * ListAdapter used when a HeaderGridView has header views. This ListAdapter   * wraps another one and also keeps track of the header views and their   * associated data objects.   *<p>This is intended as a base class; you will probably not need to   * use this class directly in your own code.   */  private static class HeaderViewGridAdapter implements WrapperListAdapter, Filterable {    // This is used to notify the container of updates relating to number of columns    // or headers changing, which changes the number of placeholders needed    private final DataSetObservable mDataSetObservable = new DataSetObservable();    private final ListAdapter mAdapter;    private int mNumColumns = 1;    // This ArrayList is assumed to NOT be null.    ArrayList<FixedViewInfo> mHeaderViewInfos;    boolean mAreAllFixedViewsSelectable;    private final boolean mIsFilterable;    public HeaderViewGridAdapter(ArrayList<FixedViewInfo> headerViewInfos, ListAdapter adapter) {      mAdapter = adapter;      mIsFilterable = adapter instanceof Filterable;      if (headerViewInfos == null) {        throw new IllegalArgumentException("headerViewInfos cannot be null");      }      mHeaderViewInfos = headerViewInfos;      mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos);    }    public int getHeadersCount() {      return mHeaderViewInfos.size();    }    @Override    public boolean isEmpty() {      return (mAdapter == null || mAdapter.isEmpty()) && getHeadersCount() == 0;    }    public void setNumColumns(int numColumns) {      if (numColumns < 1) {        throw new IllegalArgumentException("Number of columns must be 1 or more");      }      if (mNumColumns != numColumns) {        mNumColumns = numColumns;        notifyDataSetChanged();      }    }    private boolean areAllListInfosSelectable(ArrayList<FixedViewInfo> infos) {      if (infos != null) {        for (FixedViewInfo info : infos) {          if (!info.isSelectable) {            return false;          }        }      }      return true;    }    public boolean removeHeader(View v) {      for (int i = 0; i < mHeaderViewInfos.size(); i++) {        FixedViewInfo info = mHeaderViewInfos.get(i);        if (info.view == v) {          mHeaderViewInfos.remove(i);          mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos);          mDataSetObservable.notifyChanged();          return true;        }      }      return false;    }    @Override    public int getCount() {      if (mAdapter != null) {        return getHeadersCount() * mNumColumns + mAdapter.getCount();      } else {        return getHeadersCount() * mNumColumns;      }    }    @Override    public boolean areAllItemsEnabled() {      if (mAdapter != null) {        return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled();      } else {        return true;      }    }    @Override    public boolean isEnabled(int position) {      // Header (negative positions will throw an ArrayIndexOutOfBoundsException)      int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;      if (position < numHeadersAndPlaceholders) {        return (position % mNumColumns == 0)            && mHeaderViewInfos.get(position / mNumColumns).isSelectable;      }      // Adapter      final int adjPosition = position - numHeadersAndPlaceholders;      int adapterCount = 0;      if (mAdapter != null) {        adapterCount = mAdapter.getCount();        if (adjPosition < adapterCount) {          return mAdapter.isEnabled(adjPosition);        }      }      throw new ArrayIndexOutOfBoundsException(position);    }    @Override    public Object getItem(int position) {      // Header (negative positions will throw an ArrayIndexOutOfBoundsException)      int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;      if (position < numHeadersAndPlaceholders) {        if (position % mNumColumns == 0) {          return mHeaderViewInfos.get(position / mNumColumns).data;        }        return null;      }      // Adapter      final int adjPosition = position - numHeadersAndPlaceholders;      int adapterCount = 0;      if (mAdapter != null) {        adapterCount = mAdapter.getCount();        if (adjPosition < adapterCount) {          return mAdapter.getItem(adjPosition);        }      }      throw new ArrayIndexOutOfBoundsException(position);    }    @Override    public long getItemId(int position) {      int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;      if (mAdapter != null && position >= numHeadersAndPlaceholders) {        int adjPosition = position - numHeadersAndPlaceholders;        int adapterCount = mAdapter.getCount();        if (adjPosition < adapterCount) {          return mAdapter.getItemId(adjPosition);        }      }      return -1;    }    @Override    public boolean hasStableIds() {      if (mAdapter != null) {        return mAdapter.hasStableIds();      }      return false;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {      // Header (negative positions will throw an ArrayIndexOutOfBoundsException)      int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns ;      if (position < numHeadersAndPlaceholders) {        View headerViewContainer = mHeaderViewInfos            .get(position / mNumColumns).viewContainer;        if (position % mNumColumns == 0) {          return headerViewContainer;        } else {          if (convertView == null) {            convertView = new View(parent.getContext());          }          // We need to do this because GridView uses the height of the last item          // in a row to determine the height for the entire row.          convertView.setVisibility(View.INVISIBLE);          convertView.setMinimumHeight(headerViewContainer.getHeight());          return convertView;        }      }      // Adapter      final int adjPosition = position - numHeadersAndPlaceholders;      int adapterCount = 0;      if (mAdapter != null) {        adapterCount = mAdapter.getCount();        if (adjPosition < adapterCount) {          return mAdapter.getView(adjPosition, convertView, parent);        }      }      throw new ArrayIndexOutOfBoundsException(position);    }    @Override    public int getItemViewType(int position) {      int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;      if (position < numHeadersAndPlaceholders && (position % mNumColumns != 0)) {        // Placeholders get the last view type number        return mAdapter != null ? mAdapter.getViewTypeCount() : 1;      }      if (mAdapter != null && position >= numHeadersAndPlaceholders) {        int adjPosition = position - numHeadersAndPlaceholders;        int adapterCount = mAdapter.getCount();        if (adjPosition < adapterCount) {          return mAdapter.getItemViewType(adjPosition);        }      }      return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;    }    @Override    public int getViewTypeCount() {      if (mAdapter != null) {        return mAdapter.getViewTypeCount() + 1;      }      return 2;    }    @Override    public void registerDataSetObserver(DataSetObserver observer) {      mDataSetObservable.registerObserver(observer);      if (mAdapter != null) {        mAdapter.registerDataSetObserver(observer);      }    }    @Override    public void unregisterDataSetObserver(DataSetObserver observer) {      mDataSetObservable.unregisterObserver(observer);      if (mAdapter != null) {        mAdapter.unregisterDataSetObserver(observer);      }    }    @Override    public Filter getFilter() {      if (mIsFilterable) {        return ((Filterable) mAdapter).getFilter();      }      return null;    }    @Override    public ListAdapter getWrappedAdapter() {      return mAdapter;    }    public void notifyDataSetChanged() {      mDataSetObservable.notifyChanged();    }  }}

用法和ListView的addHeaderView一样。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表