ListView使用总结大全

本文深入解析Android ListView组件,涵盖其继承关系、UI属性、适配器使用、交互事件及UI更新技巧。适合Android开发者深入了解ListView的工作原理和高效使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作为Android开发中使用最多的控件之一,listView是一个以垂直方式在项目中显示View视图的列表。本篇文章将从以下几个方面详细介绍ListView的属性。

一,ListView继承关系

java.lang.Object
↳ android.view.View
↳ android.view.ViewGroup
↳ android.widget.AdapterView
↳ android.widget.AbsListView
↳ android.widget.ListView

二,Listview 常用UI属性

一个完整的ListView的配置如下:

<ListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:cacheColorHint="@color/transparent"
    android:descendantFocusability="blocksDescendants"
    android:divider="@null"
    android:listSelector="@color/transparent"
    android:overScrollMode="never"
    android:fadingEdge="none"
    android:scrollbars="none"/>

listview在拖动的时候背景图片消失变成黑色背景,等到拖动完毕我们自己的背景图片才显示出来, 解决:
android:scrollingCache=”false” 或 android:cacheColorHint=”#00000000″
android:divider="@null" //不显示分隔线
android:divider=”@drawable/list_driver” //每一项之间需要设置一个图片做为间隔
android:listSelector="@color/transparent" //当点击listview时不显示背景色
android:overScrollMode=“never” //滑到顶端和底部不显示阴影区
android:scrollbars=“none” // 滑动期间不显示scrollbar(不滑动肯定不会出现scrollbar)
当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系:android:descendantFocusability
属性的值有三种:
beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点
android:fadingEdge=“none”
不展示listView的渐变,默认不展示,如果需要展示,可以设置
android:fadingEdgeLength=“100dp”
android:requiresFadingEdge=“vertical”
展示listView上下的渐变区域,可以适用于其他类型的view。
注:ListView的高度得设置为match_parent或者具体的数值,不能设置为wrap_content,不然会造成getView重复调用测量,影响ListView的性能。

三,ListView的适配器Adapter

适配器是一个连接数据和ListView的桥梁,通过它能有效地实现数据与ListView的分离设置,使ListView与数据的绑定更加简便,易于修改。在实际工作中,常用继承自BaseAdapter的自定义适配器。BaseAdapter实现了接口ListAdapter和SpinnerAdapter,而ListAdapter和SpinnerAdapter都继承自Adapter。为什么会这样呢?因为适配器主要是用来给Spinner, ListView,GridView来填充数据的,如果每种类型的View都对应一种适配器,使用起来比较麻烦,因此BaseAdapter作为一种通用的适配器,实现ListAdapter和SpinnerAdapter中的全部和Adapter中的部分方法。因此我们自定义的适配器只需要实现Adapter中未被BaseAdapter实现的方法:
1,返回listView需要展示的item总数量

@Override
public int getCount() {   
}

2,返回listView中的每个item对象,和listView的点击事件配合使用,listView的点击事件后面介绍

@Override
public Object getItem(int position) {
    return list.get(position);
}

3,得到每个item的位置参数,使用较少

@Override
public long getItemId(int position) {
    return position;
}

4,adapter的核心方法,根据每个位置position返回对应的convertView,这里复用了模板convertView, 为了防止convertView.getTag() == null,最好在if语句中加上该限定

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Holder holder;
    if (convertView == null && convertView.getTag() == null) {
        holder = new Holder();
        arg1 = LayoutInflater.from(context).inflate(R.layout.left_list_item, null);
        holder.left_list_view = arg1.findViewById(R.id.left_list_view);
        holder.left_list_item = (TextView) arg1.findViewById(R.id.left_list_item);
        arg1.setTag(holder);
    } else {
        holder = (Holder) arg1.getTag();
    }
    return arg1;
}

private class Holder {
    private View left_list_view;
    private TextView left_list_item;
}

注:adapter中的position都是从0开始,不包含headerView和footerView的数量。

5, 禁止listView的item在setOnItemClickListener中响应点击事件,防止和自定义的点击事件发生冲突。

@Override
public boolean isEnabled(int position) {
return false;
return super.isEnabled(position);
}

还有比较重要的3个方法如下:
6,如果一个ListView中有多种展示方式,对应多个模板,为了在getView中正确调用对应的模板,需要在该方法中根据不同的position返回对应的int值,然后在getView中根据不同的返回值做不同的处理。此方法需要和getViewTypeCount配合使用,返回总共的模板数量。
在ListView的父类AbsListView中,有一个变量RecycleBin mRecycler,用来存储某一显示项布局对应的视图。实际存储在 ArrayList[] 中,该数组的长度为getViewTypeCount的返回值。RecycleBin 是AbsListView的一个内部类。 当ListView执行 setAdapter方法时,mRecycler会重置,getViewTypeCount方法会被调用。如果ListView的数据有变化,通过notifyDataSetChanged()方法是无法再次调用getViewTypeCount方法的。当ListView要显示某一项时,getItemViewType方法被调用,根据返回值在mRecycler搜索得到缓存的视图。这也是为什么getViewTypeCount返回值要比定义的视图类型常量值大的原因,否则会导致数组越界异常:java.lang.ArrayIndexOutOfBoundsException: length=2; index=2 addScrapView。但getItemViewType()不一定要求按照顺序全部符合,也不用从0开始。然后调用getView方法,缓存的视图被传递给getView方法的convertView形参。

@Override
public final int getItemViewType(int position) {
}
@Override
public final int getViewTypeCount() {
}

7,如果不希望listView中的某几项响应点击事件,则可以在该方法中返回false将其禁掉。

@Override
public boolean isEnabled(int position) {
return super.isEnabled(position);
}

四,ListView的各种交互事件

1,listView的点击事件
通过adapterView.getAdapter()获取ListView的Adapter,然后可以调用对应adapter的getItem等方法,如果有多个listView,则使用instanceof判断返回item的具体类型。View等价于convertView,可以通过findViewById获取相应的控件。在该方法中i等价于position,但是包含了headerView的数量,但是调用adapterView.getAdapter().getItem(i)获取对应item时,在adapter的getItem方法中会自动转换成去掉headerView的位置。

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
    }
});

2,listView的滑动事件

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}

onScroll在整个滑动过程中会一直调用,不管用户手指是否在屏幕上。如果firstVisibleItem + visibleItemCount = totalItemCount,则整个listView滑动到最底部。其中firstVisibleItem包含了headerView在内。

public void onScrollStateChanged(AbsListView view, int scrollState) {
}

该函数只要listview发生滚动就回调。同样与用户手指是否在屏幕无关。只要看第二个参数
scrollState:即滑动的状态。分为三种 0,1,2
=0 表示停止滑动的状态 SCROLL_STATE_IDLE
=1表示正在滚动,用户手指在屏幕上 SCROLL_STATE_TOUCH_SCROLL
=2表示正在滑动。用户手指已经离开屏幕 SCROLL_STATE_FLING
3,listView的滑动方法
lv.setSelection();
lv.setSelectionFromTop();
lv.smoothScrollToPosition();
lv.smoothScrollToPositionFromTop();
在子线程run方法中调用上述滑动方法,会把新消息添加到 Adapter 中并且执行 Adapter.notifyDataSetChanged()

listView.post(new Runnable() {
    @Override
    public void run() {
    }
});

4,在当前可见区域的操作,适用于更新某一项可见条目
获取当前可见子项
listView.getChildAt(index),其中listView.getFirstVisiblePosition() =< index <= listView.getLastVisiblePosition(),index = position - listView.getFirstVisiblePosition()
获取可见条目总数:
listView.getChildCount
5, listView加载headerView和footerView的方法
listView.addHeaderView
listView.removeHeaderView
listView.addFooterView
listView.removeFooterView
listView.getHeaderViewsCount()

五,ListView UI更新

当清空listView数据源时,如果长时间不调用adapter.notifyDataSetChanged()会导致页面listView展示部分空白,可以通过新定义一个list避免该问题,但是背后的原理不是很清楚,最好将list数据源的更新放在UI线程。
listView在更新UI时会记录上次的滑动位置,如果页面item太少会导致页面滑不上去,手动做补偿后需要调用listView的滑动方法setSelectionFromTop。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值