ListView
布局
宽高尽量都要使用fill_parent,因为Draw时fill_parent的计算方法会比较简单,只要跟父元素的大小相似就行,但是wrap_content就会比较复杂,自适应的时候会一直考量它的宽和高,根据内容(也就是它的子Item)计算宽高。可能导致measure过程会反复执行,如果父元素也是wrap_content,这个过程会更加漫长。而这样可能会导致一些奇葩事情的发生,例如按钮不响应点击事件。
View的复用优化和item 0重复调用问题
ListView作为列表式View中的常用简单View,成为Android开发必须要掌握的技能。而使用ListView又必须使用Adapter。所以,在很多教程、书籍、博客中,ListView和Adapter成对出现。而所谓的对ListView的itemView复用优化和item 0重复调用的问题,也就抛给了ListView。但从实际代码来看,itemView复用优化和item 0重复调用的问题,是属于Adapter的代码,是属于Adapter的优化,并且由于Adapter是通用的(可用于其它AdapterView子类,例如,GridView),所以,这种优化问题也同样会出现GridView上。故,这里不会去探讨这个问题的解决,而是会在Adapter中去说明,详见Adapter。
小知识点
设置item间的分隔线
1.不指定,listview默认带有分隔线
2.设置分隔线,有java代码和xml代码两种方式,第一行代码都是设置分隔线的颜色,第二行代码都是设置分隔线的高度。
listView.setDivider();
listView.setDividerHeight();
android:divider="@android:color/darker_gray"
android:dividerHeight="@dimen/activity_horizontal_margin"
3.不显示分隔线:同上述两种方法:
listView.setDivider(null);
listView.setDividerHeight(0);
android:divider="@null"
android:dividerHeight="0dp"
设置滚动条
默认的,ListView在滚动时候会在右侧显示滚动条,指示当前滑动的位置,我们可以指定 android:scrollbar相关属性,来对滚动条进行设置滚动条显示的样式,若是想要隐藏滚动条,设置如下:
android:scrollbars="none"
设置item点击效果
同样还是默认的,ListView的item在点击的时候会有一个点击效果,5.0以上是波纹效果,以下是改变背景颜色的效果,我们可以通过下面这个属性的两种不同实现方式来取消掉这个效果,当然也可以通过这个属性自定义效果:
android:listSelector="@null"
android:listSelector="@android:color/transparent"
设置ListView首个显示条目是第几项
1.如果是以Item为显示单位,默认首个显示条目是第1个Item,想要指定某一个Item作为首个显示条目可设置一个int值来进行设置:
int i = 5;
listView.setSelection(i);
2.如果是手势滑动而形成的像素点xy坐标为显示单位,就需要用到以下方法:
listView.scrollTo(listScrolledX, listScrolledY);//scrollTo()是view的方法
3.上述两种方法的移动过程都是在瞬间完成,如果想要看到平滑移动的效果:
listView.smoothScrollByOffset(offset);
listView.smoothScrollBy(distance,duration);
listView.smoothScrollToPosition(index);
获取ListView的某一具体子View
listView.getChildAt(i);
在此基础上可遍历ListView的所有Item。
另外
listView.getCount();
获得ListView的子Item的总数。
处理空ListView
当列表内没有数据或正在请求数据的时候,我们可以先设置一个空view,给用户以更好的体验:
listView.setEmptyView(view);
ListView触摸监听
点击监听
采用OnTouchListener是View级别的监听事件。故会在自定义View中说明。此处不做处理。
滑动监听
采用OnScrollListener是AbsListView级别的监听事件,AbsListView主要有两个子类,一个就是我们现在说的ListView,还有就是GridView。所以我们在这里说一下这个监听事件。
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState){
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
//滑动停止时调用
break;
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
//正在滚动时调用
break;
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
/*手指抛动时,即手指用力滑动
在离开后ListView 由于惯性继续滑动
* */
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//滚动时一直调用
//firstVisibleItem:当前能看见的第一个Item的ID(从0开始)
//visibleItemCount:当前能看见的Item总数(包括没有显示完整的Item)
//totalItemCount:整个ListView的Item总数
}
});
利用这些参数和状态,我们就可以很方便的做出逻辑上的一些处理,比如:
判断ListView是否滚动到了最后一行
if(firstVisibleItem + visibleItemCount == totalItemCount
&& totalItemCount - Count > 0){
//滚动到最后一行
}
当然,ListView已经为我们封装好了一些方法,用于获取当前可视Item的位置:
//获取可视区域内最后一个Item的id
listView.getLastVisiblePosition();
//获取可视区域内第一个Item的Id
listView.getFirstVisiblePosition();
判断ListView滚动方向
if (firstVisibleItem > lastVisibleItemPosition){
//上滑
} else if (firstVisibleItem < lastVisibleItemPosition){
//下滑
}
lastVisibleItemPosition = firstVisibleItem;
列表滑动时的卡顿优化
列表的优化有很多方面,这里仅仅说和ListView有关的一方面:控制异步任务的执行频率。如例,一个显示图片的列表,图片采用异步加载,这本身已属优化,但是如果用户刻意的频繁上下滑动,这就会在一瞬间产生上百个异步任务,这些异步任务造成线程池的拥堵的同时还会带来大量的UI更新,这样做不仅没有意义还会造成卡顿。解决:在列表滑动时停止加载图片。
ListView代码:
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE){
mIsListViewIdle = true;
adapter.notifyDataSetChanged();
} else {
mIsListViewIdle = false;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
Adapter中代码:
if(mIsListViewIdle){
//加载图片
}
关于优化列表请看。