一、简介
ListView列表视图控件是Android中常用的控件之一,其直接继承了AbsListView,是一个以垂直方式在项目中显示View视图的列表。ListView的数据项,来自一个继承了ListAdapter接口的适配器。
二、ListView常用属性和方法
ListView的常用属性一般就是用来设置列表的间隔、分割线、表头、表尾等属性的,常用属性有以下几个,并且Android也为其提供了对应的setter/getter方法:
android:divider:使用一个Drawable或者color设置数据项之间的间隔样式。
android:dividerHeight:设置数据项之间的间隔距离。
android:entries:设置一个资源Id用于填充ListView的数据项。
android:footerDividersEnabled:设定列表表尾是否显示分割线,如果有表尾的话。
android:headerDividerEnabled:设定列表表头是否显示分割线,如果有表头的话。
ListView提供了一些方法,用于操作ListView。这里介绍一些常用的方法,更多的请参见API文档:
void addFooterView(View v):添加表尾View视图。
boolean removeFooterView(View v):移除一个表尾View视图。
void addHeaderView(View v):添加一个表头View视图。
boolean removeHeaderView(View v):移除一个表头View视图。
ListAdapter getAdapter():获取当前绑定的ListAdapter适配器。
void setAdapter(ListAdapter adapter):设置一个ListAdapter适配器到当前ListView中。
void setSelection(int posotion):设定当前选中项。
long[] getCheckItemIds():获取当前选中项。
作为一个列表选择控件,ListView具有一些选中选项可以触发的事件,但它本身没有定义这些事件,均继承自间接父类AdapterView。ListView支持的几个常用事件有以下几个:
AdapterView.OnItemCLickListener:列表项被点击时触发。
AdapterView.OnItemLongClickListener:列表项被长按时触发。
AdapterView.OnItemSelectedListener:列表项被选择时触发。
三、适配器
适配器是一个连接数据和AdapterView的桥梁,通过它能有效地实现数据与AdapterView的分离设置,使AdapterView与数据的绑定更加简便,修改更加方便。将数据源的数据适配到ListView中的常用适配器有:ArrayAdapter、SimpleAdapter。
ArrayAdapter最为简单,只能展示一行字;
SimpleAdapter有最好的扩充性,可以自定义各种各样的布局,除了文本外,还可以放ImageView(图片)、Button(按钮)、CheckBox(复选框)等等;
但是实际工作中,常用自定义适配器。即继承于BaseAdapter的自定义适配器类。
四、使用步骤
1、创建 my_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/my_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
2、创建一个item的布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/cardview_shadow_start_color"
>
<ImageView
android:id="@+id/img"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:padding="5dp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/img"
android:layout_marginLeft="10dp"
android:padding="30dp"
android:textColor="@color/black" />
</RelativeLayout>
2、在Activity用ListView绑定Adapter
public class MyListActivity extends AppCompatActivity{
ListView listView;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_list);
listView = findViewById(R.id.my_list_view);
String[] arr = {"菠萝","芒果","石榴","葡萄"};
//ArrayAdapter适配器
// ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,arr);
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
for (int i = 0; i < arr.length; i++) {
Map<String, String> map = new HashMap<String, String>();
map.put("name", arr[I]);
map.put("img", String.valueOf(R.drawable.ic_launcher_background));
list.add(map);
}
// SimpleAdapter适配器
// 使用SimpleAdapter来作为ListView的适配器,比ArrayAdapter能展现更复杂的布局效果。为了显示较为复杂的ListView的item效果,需要写一个xml布局文件,来设置ListView中每一个item的格式。
// SimpleAdapter adapter = new SimpleAdapter(this,list,R.layout.my_sm_list_item,new String[]{"name","img"},new int[]{R.id.name,R.id.img});
//自定义BaseAdapter适配器
MyAdapter adapter = new MyAdapter(this,R.layout.my_sm_list_item,list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MyListActivity.this, arr[position], Toast.LENGTH_SHORT).show();
}
});
}
下面是一个自定义的Adapter
public class MyAdapter extends BaseAdapter {
private Context mContext;
private List<Map<String, String>> mList;
private int mViewId;
public MyAdapter(Context context,int viewId,List<Map<String, String>>list) {
this.mContext = context;
this.mList = list;
this.mViewId = viewId;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(mContext).inflate(mViewId, null);
TextView nameTX = convertView.findViewById(R.id.name);
ImageView imageV = convertView.findViewById(R.id.img);
nameTX.setText(mList.get(position).get("name"));
imageV.setImageResource(Integer.parseInt(mList.get(position).get("img")));
return convertView;
}
class ViewHolder {
private TextView nameTX;
private ImageView imageV;
}
}
五、ListView的优化
目前我们ListView的运行效率是很低的,因为在自定义的Adapter的 getView()方法中,每次都将布局重 新加载了一遍,将快速滚动的时候, 这将会成为性能的瓶颈。这里我们可以利用重用机制去优化。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null) {
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(mViewId, null);
viewHolder.nameTX = convertView.findViewById(R.id.name);
viewHolder.imageV = convertView.findViewById(R.id.img);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)convertView.getTag();
}
viewHolder.nameTX.setText(mList.get(position).get("name"));
viewHolder.imageV.setImageResource(Integer.parseInt(mList.get(position).get("img")));
return convertView;
}
class ViewHolder {
private TextView nameTX;
private ImageView imageV;
}