public void addFooterView(View v, Object data, boolean isSelectable) {
    ListAdapter mAdapter = getAdapter();
    if (mAdapter != null && !(mAdapter instanceof HeaderViewGridAdapter)) {
      throw new IllegalStateException(
          "Cannot add header view to grid -- setAdapter has already been called.");
    }

    ViewGroup.LayoutParams lyp = v.getLayoutParams();

    FixedViewInfo info = new FixedViewInfo();
    FrameLayout fl = new FullWidthFixedViewLayout(getContext());

    if (lyp != null) {
      v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
      fl.setLayoutParams(new AbsListView.LayoutParams(lyp.width, lyp.height));
    }
    fl.addView(v);
    info.view = v;
    info.viewContainer = fl;
    info.data = data;
    info.isSelectable = isSelectable;
    mFooterViewInfos.add(info);

    if (mAdapter != null) {
      ((HeaderViewGridAdapter) mAdapter).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.
   * @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.");
    }

    ViewGroup.LayoutParams lyp = v.getLayoutParams();

    FixedViewInfo info = new FixedViewInfo();
    FrameLayout fl = new FullWidthFixedViewLayout(getContext());

    if (lyp != null) {
      v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
      fl.setLayoutParams(new LayoutParams(lyp.width, lyp.height));
    }
    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 onCallBackData,
    // we need to notify the observer
    if (adapter != null) {
      ((HeaderViewGridAdapter) adapter).notifyDataSetChanged();
    }
  }