Android 在ListView使用addHeader注意的问题
来源:互联网 发布:tp886 访客网络 编辑:程序博客网 时间:2024/05/17 05:00
一些APP:
他们布局很类似。顶部是搜索栏 往下依次是轮播,分类 ,活动主题,推荐产品列表,底部Bar。 如果用整个用ScrollView实现的话,实现起来很容易,但是最下面的推荐产品由于是不确定数量的,有可能还挺多,那么
1.产品列表用ListView,需要解决和ScrollView的冲突及ListView的高度问题
2.产品列表用ScrollView或着LinearLayout,数量多,图片多的话,由于没有缓存重用,有可能有性能问题
换做用ListView来实现,如果不用Header,用itemType来区分的话,要创建N个type,实现起来略显复杂。
ListView 对Header,Foot而的数量是没有限制的,用ListView和addHeader处理这种情形是比较合适的(当然顶部搜索和底部Bar是除外的)。
addHeader,addFooter这两个方法使用很简单,就不赘述。主要记录一下使用的时候可能会遇到的坑。
1.关于Header的隐藏和显示
ListView 对 Header相关的API共有 listView.getHeaderViewsCount();
listView.addHeaderView(View v);
listView.removeHeaderView(View v);
listView.areHeaderDividersEnabled();
四个函数,没有控制顺序,及是否显示某个Header的API。
怎么隐藏一个Header? 如果不再展示可以使用emoveHeaderView
,再次需要展示呢?就会有顺序的问题。
再有想到的是将headerView设为GONE
,理论上这是对的,但是实际上却没有效果,留下了一个空白的占位,也就是说他的parent去正确的响应及布局。现在一般的解决方案是:如果要隐藏一个headerView,就将发的子View的可见性设为GONE
或者高度设为0。显示的时候View的可见性设为VISIBLE
.
最终的解决方案是:
开始的时候将所有的HeaderView都按照顺序使用addHeaderView添加到ListView中,通过控制headerView的子View的可见性来控制是否显示。
2.关于setAdapter和addHeaderView的执行顺序的问题
ListView想要添加headerview的话,就要通过addHeaderView
这个方法,然后想要为ListView设置数据的话,就要调用setAdapter
方法了。但是,在低版本的设备(API<=17)上会报 java.lang.IllegalStateException: Cannot add header view to list -- setAdapter has already been called.
的异常。这是因为我们在addHeaderView之前已经调用了setAdapter
.
通过源码来看:
API-17(Android 4.2)
public void addHeaderView(View v, Object data, boolean isSelectable) { if (mAdapter != null && ! (mAdapter instanceof HeaderViewListAdapter)) { throw new IllegalStateException( "Cannot add header view to list -- setAdapter has already been called."); } FixedViewInfo info = new FixedViewInfo(); info.view = v; 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 (mAdapter != null && mDataSetObserver != null) { mDataSetObserver.onChanged(); }}
API-18(Android 4.3)
public void addHeaderView(View v, Object data, boolean isSelectable) { final FixedViewInfo info = new FixedViewInfo(); info.view = v; info.data = data; info.isSelectable = isSelectable; mHeaderViewInfos.add(info); // Wrap the adapter if it wasn't already wrapped. if (mAdapter != null) { if (!(mAdapter instanceof HeaderViewListAdapter)) { mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); } // In the case of re-adding a header view, or adding one later on, // we need to notify the observer. if (mDataSetObserver != null) { mDataSetObserver.onChanged(); } }}
可以看到在API<=17中,如果adapter不是空直接抛出异常,而在API>17中,对mAdapter 进行了判断,如果是空,先把header记录在mHeaderViewInfos,在setAdapter的时候再将header及adapter封装在HeaderViewListAdapter中,如果不是空直接构建一个HeaderViewListAdapter。
所以为了保证兼容性的问题,在setAdapter之前要把所有的header都加入到ListView里面。setAdapter之后不要再addHeaderView了。
3.在onItemClickListen中position问题
通过源码知道,如果一个ListView 存在Header或者Footer,ListView内部会将adapter封装在一个HeaderViewListAdapter里面,那么在onItemClickListen里面取到是包含header在内的item的位置,已经不是我们一般意义上的数据源的位置。所以实际上点击的position=取到的position-headerConunt
;当然可以直接这样做换算,实际上HeaderViewListAdapter里面已经帮我们做了:
HeaderViewListAdapter.java
public Object getItem(int position) { // Header (negative positions will throw an IndexOutOfBoundsException) int numHeaders = getHeadersCount(); if (position < numHeaders) { return mHeaderViewInfos.get(position).data; } // Adapter final int adjPosition = position - numHeaders; int adapterCount = 0; if (mAdapter != null) { adapterCount = mAdapter.getCount(); if (adjPosition < adapterCount) { return mAdapter.getItem(adjPosition); } } // Footer (off-limits positions will throw an IndexOutOfBoundsException) return mFooterViewInfos.get(adjPosition - adapterCount).data; }
在HeaderViewListAdapter的getItem()
中adjPosition就是真正数据源中国的position。
所以在onItemClickListen中取数据的时候使用 parent.getAdapter().getItem(position);
来获取你真正的实体。(自定义的Adapter要重写getItem()
方法,不要返回null)
source:http://www.zhangningning.com.cn/blog/Android/Android_listview_addheade.html
- Android 在ListView使用addHeader注意的问题
- Android 在ListView使用addHeader注意的问题
- Android 4.4以下ListView addHeader和addFooter放在setAdapter之后导致异常的原因分析和解决
- Android使用ListView应该注意的地方
- Android使用ListView应该注意的地方
- Android使用ListView应该注意的地方
- Android使用ListView应该注意的地方
- Android使用ListView应该注意的地方
- Android使用ListView应该注意的地方
- Android使用ListView应该注意的地方
- Android ListView适配器BaseAdapter中getItemViewType需要注意的问题
- android ListView item 点击设置背景图片需要注意的问题
- ListView使用addHeaderView或addFooterView需注意的问题
- ListView需要注意的问题
- ListView 优化注意的问题
- 有关ListView注意的问题
- android[技巧]使用ListView应该注意的地方
- Android水平方向ListView的使用和注意点
- CommunicationsException: Communications link failure
- 原生js表单验证代码
- 设计模式——代理VS中介者
- 51NOD 1087 1 10 100 1000
- 《Java虚拟机原理图解》4.JVM机器指令集
- Android 在ListView使用addHeader注意的问题
- Redis排序相关
- uva 10714
- 回文串---manacher算法
- 求两个有序数组的中位数或者第k小元素
- OpenGL - VS 配置 OpenGL - 一
- java读取properties文件的几种方法
- POJ 2676/2918——数独DFS
- 浅析java中final,finally,finalize