Android UI之GridView

来源:互联网 发布:工业机器手臂编程 编辑:程序博客网 时间:2024/05/21 00:16

GridView(AdapterView)

1 属性:AllowSorting属性指示控件中支持排序。

2 常用属性

2.1 设置按下时背景透明

android:listSelector="@android:color/transparent"

2.2 取消滚动条

android:scrollbars="none"

2.3 实用属性解析

<!-- grid元素之间的竖直间隔 -->android:verticalSpacing="5px"<!-- grid元素之间的水平间隔 -->android:horizontalSpacing="5px"<!-- 表示有多少列,如果设置为auto_fit,将根据columnWidth和Spacing来自动计算 -->android:numColumns="auto_fit"<!-- 一般建议采用有像素密度无关的dip或者dp来表示 -->android:columnWidth="100px"<!-- 如何填满空余的位置,模拟器采用WVGA800*480,每排4列,有4*100+5*3=415,还余65px的空间;(1).如果是columnWidth,则这剩余的65将分摊给4列,每列增加16/17px。(2).如果是spacingWidth,则分摊给中间3个间隔空隙.(3).如果是spacingWidthUniform,则分摊给5个间隔(包括左右两边) -->android:stretchMode="columnWidth"

(1).columnWidth

这里写图片描述

(2).spacingWidth
这里写图片描述

(3).spacingWidthUniform
这里写图片描述

3 为GridView添加HeaderView

思路的具体实现是使用ListView的addHeaderView()来添加HeaderView,而ListView的每一行都放一个LinearLayout来保存一行的item,这里要注意的是item的个数和ListView行数的关系。

http://blog.csdn.net/zhzhyang0313/article/details/39163735

package com.android.photos.views;  import android.content.Context;  import android.database.DataSetObservable;  import android.database.DataSetObserver;  import android.util.AttributeSet;  import android.view.View;  import android.view.ViewGroup;  import android.widget.AdapterView;  import android.widget.Filter;  import android.widget.Filterable;  import android.widget.FrameLayout;  import android.widget.GridView;  import android.widget.ListAdapter;  import android.widget.WrapperListAdapter;  import java.util.ArrayList;  /**  * A {@link GridView} that supports adding header rows in a  * very similar way to {@link ListView}.  * See {@link HeaderGridView#addHeaderView(View, Object, boolean)}  */  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();      }      @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;              }          }      }      @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();          }      }  }  
0 0