您的位置:首页 > 其它

listview

2015-07-06 14:51 316 查看

getChildAt

Listview可以有header有footer,在普通listview的上下方,随着滚动会出现或者消失
Listview的mChildren是可见部分的item(可以是header,footer)的集合,所以ListView.getChildAt(int position),
这个position指的是在可视的item中的索引,跟cursor里的位置是大不一样的。可以看看ListView.getChildCount()函数得到个数是小于或等于Cursor里的个数的(不考虑header的话)。虽然一共可能有20条数据,但是界面只能看到8条,那么这个ChildCount大约就是8了。

getTop

View firstChild =view.getChildAt(0);
int top = firstChild.getTop();
这段代码是获取第一个可见项与listview本身的高度距离,如图,测试数据1有部分在屏幕外,有部分在屏幕内,假设在屏幕外部分为20px,屏幕内部分为30px,那他的top值就是-20px




listview滚动距离

我们怎么知道一个listview滚动了多少呢,可能会先想到视图的基类方法getScrollY(),但此方法给ScrollView使用没有问题,因为ScrollView没有复用机制。ListView的父容器里永远只有可见的item,整个容器其实并没有相对屏幕移动,因此getScrollY()总是为0。

有方法如下:
public int getScrollY() {
View c = mListView.getChildAt(0);
if (c == null) {
return 0;
}
int firstVisiblePosition = mListView.getFirstVisiblePosition();
int top = c.getTop();
return -top + firstVisiblePosition * c.getHeight() ;
}

这个方法只适用于所有的item一样高的


分割线问题

使用listview自带的分割线经常出现奇怪的问题,比如顶部多了跟线(比如item数量为0,只有head),比如底部少了跟线,可以看下面的文章

http://blog.csdn.net/xiaoxiaobian3310903/article/details/7182231
http://www.cnblogs.com/mengshu-lbq/archive/2012/04/07/2435883.html http://gundumw100.iteye.com/blog/1169065
我觉得还是不要用他的线好了,自己在viewholder里面画跟线得了


改变数据size的操作必须在主线程

listview对应的数据arraylist,会由一些操作,比如add,remove,这些操作会改变数组的size,尽量把这些操作和notifyDataSetChanged一起放到ui线程中去,如果数据操作在非ui线程内,可能会导致崩溃,日志如下

E/AndroidRuntime(16779):java.lang.IllegalStateException: The content of the adapter has changed butListView did not receive a notification. Make sure the content of your adapteris not modified from a background thread, but only from the UI thread. Makesure
your adapter calls notifyDataSetChanged() when its content changes.

这个崩溃是listview的layoutChildren触发的,代码如下

[java] view
plaincopy

if (mItemCount == 0) {

resetList();

invokeOnItemScrollListener();

return;

} else if (mItemCount != mAdapter.getCount()) {

throw newIllegalStateException("The content of the adapter has changed but "

+ "ListView didnot receive a notification. Make sure the content of "

+ "your adapter isnot modified from a background thread, but only from "

+ "the UI thread.Make sure your adapter calls notifyDataSetChanged() "

+ "when itscontent changes. [in ListView(" + getId() + ", " + getClass()

+ ") withAdapter(" + mAdapter.getClass() + ")]");

}

listview会在layoutChildren内部去检查mItemCount !=mAdapter.getCount()。

如果我们在子线程改变数据,在主线程内更新notifyDataSetChanged,这2个之间有时间差,如果在这2个操作之间 listview执行onLayout,就会调用layoutChildren,此时mAdapter.getCount()已经改变,但是还没有notifyDataSetChanged,所以mItemCount没有变化,导致崩溃

可参考http://www.cnblogs.com/monodin/p/3874147.html

参考资料

http://blog.csdn.net/lilybaobei/article/details/8142987
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: