第四章 ListView 使用技巧

2018-03-01 11:12:37来源:https://www.jianshu.com/p/47ae37483c20作者:YoungerDev人点击

分享


说实话 就是一个刚做android 的同学也知道ListView 的使用吧;
在Android 开发中ListView出现的频率是相当的高,可能最近有点没落了,因为在5.X的时候 增加了RecyclerView ,ListView 能实现的,RecyclerView 都能实现,且效率更高, 关于一会要写的优化,RV 已经帮封装好了,不需要再写这些一堆代码了,使用起来更加方便,实现的效果更多,比如 竖向,横向的list,瀑布流等都是默认的选项,但是今天还是写下ListView的种种吧,也算是对ListView 的一个使用总结;


1. 使用ViewHolder 模式提高效率

ViewHolder模式充分利用了ListView 的视图缓存机制,避免每次调用getView 的时候都去findViewById() 实例化控件,这样在数据超过一屏幕可以展示下的情况下都是可以提高效率的.


设置分割线
这个比由于是直接支持的,比RV好处理多了



直接在布局文件里写
android:divider="@android:color/dark_gray"
android:dividerHeight="10dp"
如果不想设置 android:divider="@null"



取消listView item 的点击效果



android:listSelector="#0000"



设置需要显示在第几项



listView.setSelection(N);
类似scrollTo 瞬间完成移动,或者可以使用如下代码实现平滑移动
listView.smoothScrollBy(distance,duration);
listView.smoothScrollByOffset(offset);
listView.smoothScrollToPosition(index);



动态修改Listview



list.add(bean);
adapter.notifyDataSetChanged();



ListView 的滑动监听

除了下面要介绍的 监听方法 还可以通过 使用 GestureDetector手势识别,VelocityTracker 滑动速度检测等辅助类来完成监听;


            @Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
//触摸是操作
break;
case MotionEvent.ACTION_MOVE:
//移动时操作
break;
case MotionEvent.ACTION_UP:
//手指抬起时操作
break;
}
return false;
}
});

OnScrollListener


        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
switch (i){
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
// 滑动停止时
break;
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
// 正在滚动
break;
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
// 手指抛动时, 用手指用户滑动手指离开 由于惯性继续滑动
break;
}
}
@Override
public void onScroll(AbsListView absListView,
int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//滚动时会一直调用这个方法
}
});

可以在 onScroll 方法中做一些事
比如 判断是不是滑到最后一个了
if(firstVisibleItem +visibleItemCount == totalItemCount && totalItemCount > 0 ){
//滑动到最后一行
}


还可以判断 滚动的方法问题;
if(firstVisibleItem > lastVisibleItemPosition){
//上滑
} else if(firstVisibleItem < lastVisibleItemPosition){
//下滑
}
lastVisibleItemPosition = firstVisibleItem;


//获取可视区域内最后一个item的id 同样的也有第一个;
listView.getLastVisiblePosition();


重写ListView 做一个有弹力十足的 ListView ;


 @Override
protected boolean overScrollBy(int deltaX, int deltaY,
int scrollX, int scrollY, int scrollRangeX,
int scrollRangeY, int maxOverScrollX,
int maxOverScrollY, boolean isTouchEvent) {
return super.overScrollBy(deltaX, deltaY,
scrollX, scrollY, scrollRangeX, scrollRangeY,
maxOverScrollX, maxOverScrollY, isTouchEvent);
}

重写ListView 重写这个方法,修改 maxOverScrollY 这个字,在return 的时候 返回我们定义的值就行了, 默认的是0 ,没有效果,


为了更好的适配大部分手机,可以根据手机 的 density来计算具体的值


        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float density = metrics.density;
mMaxOverScrollY = (int)(density * maxOverScrollY);

看到 这块的时候,我想讲一个我在实际项目中用到的 监听屏幕滑动的案例;
需求就是 一个页面,默认的时候不显示title ,屏幕上滑时,title由无到有,一个渐变过程, 其实就是监听ScrollView 的滚动事件 setOnScrollListener 下面就是试下这个需求的代码,大致可以看懂吧


 @Override
public void onScroll(int scrollY) {
float k = Math.abs(scrollY);
if (k <= 50) {
//滑动的距离小于50 时 title是透明的,不显示
rlTitle.getBackground().mutate().setAlpha(0);
// tv_top_title.setVisibility(View.GONE);
rlTitle.setVisibility(View.GONE);
common_title_bottom_line.setVisibility(View.GONE);
} else if (k > 50 && k < 200) {
//50到200之间随着滑动的距离变化来调整透明度
rlTitle.getBackground().mutate().setAlpha((int) ((k - 50) / 150 * 255));
if ((int) ((k - 50) / 150 * 255) > 100) {
// tv_top_title.setVisibility(View.VISIBLE);
rlTitle.setVisibility(View.VISIBLE);
common_title_bottom_line.setVisibility(View.VISIBLE);
} else {
// tv_top_title.setVisibility(View.GONE);
rlTitle.setVisibility(View.GONE);
common_title_bottom_line.setVisibility(View.GONE);
}
} else {
// 大于200后 就一直显示着 不透明的title
rlTitle.getBackground().mutate().setAlpha(255);
// tv_top_title.setVisibility(View.VISIBLE);
rlTitle.setVisibility(View.VISIBLE);
common_title_bottom_line.setVisibility(View.VISIBLE);
}
}

代码中有一个内容,需要注意一下 rlTitle.getBackground().mutate().setAlpha(255); 的 mutate() 当时为什么要加这个方法呢 是我在想通过代码动态改变 title的背景的透明度时,他把整个页面的背景搞得混乱了,完全不是想要的效果了, 网上查到原来是因为:



我明明只给title的背景设置了着色的 Drawable,为什么其他的颜色色值也改变了呢?这是因为 Android 为了优化系统性能,资源 Drawable 只有一份拷贝,你修改了它,等于所有的都修改了。 也是就是他们是共享状态的 ;幸运的是,Drawable 提供了一个方法 mutate(),来打破这种共享状态,等于就是要告诉系统,我要修改(mutate)这个 Drawable。给 Drawable 调用 mutate() 方法以后。



所以以后遇到这种背景颜色错乱,可以看看是不是这个原因导致的;
好了 今天这一章就先这样吧;后续如果想到更好的内容,会完善进来;








最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台