第四章 ListView 使用技巧

Android 群英传笔记
第一章Android体系与系统架构
第二章 Android开发工具及技巧
第三章 Android控件架构与事件拦截机制
第四章 ListView 使用技巧
第五章 Android Scroll 分析
第六章 Android 绘图机制与屏幕适配
第七章 Android 动画机制与使用技巧
第八章 Activity与Activity调用栈分析
第九章 Android 系统信息与安全机制
第十章 Android性能优化
本文出自:
http://www.jianshu.com/u/a1251e598483

说实话 就是一个刚做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() 方法以后。

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

你可能感兴趣的:(第四章 ListView 使用技巧)