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){
            //加载图片
        }

关于优化列表请看。

results matching ""

    No results matching ""