目录
adapter.notifyDataSetChanged():该方法来通知ListView来实时更新显示。
一、ListView常用属性
属性 | 理解 |
---|---|
android:divider | 列表之间绘制的颜色或者图片。 一般用于分隔。 如果不想要列表之间的分割线,可以设置属性为@null |
android:dividerHeight | divider的高度 |
android:stackFromBottom | 在ListView和GridView中使用,使它们的内容从底部开始显示。默认是false从顶部开始显示,如果设置为true则从底部开始显示。 |
android:listSelector | 用来指明列表当前选中的选项的图片或颜色 |
android:drawSelectorOnTop | 设置为true时,选择后的图片会遮住字符,默认是false |
二、ArrayAdapter
item布局文件中有且只能有一个TextView标签
/**
* 参数一:上下文对象
* 参数二:布局文件的id,该布局文件有且只能有一个TextView标签
* 参数三:原始数据,List集合或数组都可以。
*/
ArrayAdapter(Context context, int resource, List<T> objects)
1、案例
<?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"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ListView
android:id="@+id/list_array"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
public class MainActivity extends AppCompatActivity {
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.list_array);
ArrayList list = new ArrayList();
for (int i = 0; i < 30; i++) {
list.add("你好" + i);
}
ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list);
listView.setAdapter(arrayAdapter);
}
}
2、效果图
三、SimpleAdapter
/**
* 参数一:上下文对象
* 参数二:list集合,数据源
* 参数三:布局文件,该布局为ListView每个item的布局
* 参数四:原始数据中Map集合的key组成的字符串数组
* 参数五:要把原数数据每个key对应的值赋值给的View的id组成的数组,注意要和参数四对应起来
*/
SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
1、案例
定义item的布局
<?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"
android:orientation="vertical">
<TextView
android:id="@+id/item_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/item_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
public class MainActivity extends AppCompatActivity {
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.list_array);
List<HashMap<String, Object>> mapList = new ArrayList<>();
for (int i = 0; i < 30; i++) {
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("key1", "value1_" + i);
hashMap.put("key2", "value2_" + i);
mapList.add(hashMap);
}
SimpleAdapter adapter = new SimpleAdapter(this
, mapList
, R.layout.list_array
, new String[]{"key1", "key2"}
, new int[]{R.id.item_1, R.id.item_2});//对应的view
listView.setAdapter(adapter);
}
}
2、效果图
四、BaseAdapter
定义一个类继承BaseAdapter,必须重写4个方法:
- getCount()
返回原数数组或集合的长度。 - getItem(int position)
返回原数数据的相应index的对象。 - getItemId(int position)
返回值一般与position相同。 - getView(int position, View convertView, ViewGroup parent)
position:要显示的Item的位置。
convertView:移出屏幕的item的view对象的回收的old view。用于将之前加载好的布局进行缓存,以便之后可以进行重用。
parent:该ListView对象本身。
1、案例
定义item的布局
<?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="50dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="50dp" />
<TextView
android:id="@+id/item_url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</LinearLayout>
自定义适配器
public class MyBaseAdapter extends BaseAdapter {
Context mContext;
List<String> mlist;
public MyBaseAdapter(Context context,List<String> list){
mContext = context;
mlist = list;
}
@Override
public int getCount() {
return mlist.size();
}
@Override
public Object getItem(int position) {
return mlist == null ? null : mlist.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = View.inflate(mContext,R.layout.list_item,null);
TextView tvText = view.findViewById(R.id.item_url);
ImageView imageView = view.findViewById(R.id.image);
tvText.setText(mlist.get(position));
imageView.setImageResource(R.mipmap.ic_launcher);
return view;
}
}
public class MainActivity extends AppCompatActivity{
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.list_array);
List<String> list = new ArrayList<>();
for (int i = 0; i < 30; i++) {
list.add("你好" + i);
}
MyBaseAdapter myBaseAdapt = new MyBaseAdapter(this, list);
listView.setAdapter(myBaseAdapt);
}
}
2、效果图
3、提升效率
该ListView的运行效率是很低的,因为在MyBaseAdapter的getView()的方法中,每次都将布局重新加载了一遍。
仔细观察会发现getView()方法中还有一个convertView参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用。
修改MyBaseAdapter中的代码,如下所示:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/*View view = View.inflate(mContext,R.layout.list_item,null);
TextView tvText = view.findViewById(R.id.item_url);
ImageView imageView = view.findViewById(R.id.image);
tvText.setText(mlist.get(position));
imageView.setImageResource(R.mipmap.ic_launcher);
return view;*/
ViewHolder holder = null;
if (null == convertView) {
convertView = View.inflate(mContext,R.layout.list_item,null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvText.setText(mlist.get(position));
holder.imageView.setImageResource(R.mipmap.ic_launcher);
return convertView;
}
class ViewHolder{
private TextView tvText;
private ImageView imageView;
ViewHolder(View view) {
tvText = view.findViewById(R.id.item_url);
imageView = view.findViewById(R.id.image);
}
}
可以看到,现在在getView()方法中进行了判断。如果convertView为null,则去加载布局;如果不为null,则直接对convertView进行重用。
新增了一个内部类ViewHolder ,用于对控件的实例进行缓存。
当convertView为null的时候,创建一个ViewHolder对象,并将控件的实例都存放在ViewHolder里,然后调用View的setTag()方法,将ViewHolder对象存储在View中。当convertView不为null的时候,则调用View的getTag()方法,把ViewHolder重新取出。这样所有控件的实例都缓存在了ViewHolder里,就没有每次都通过findViewById()方法来获取控件实例。
五、CursoAdapter
定义一个类继承了CursoAdapter,必须重写2个方法:
- newView(Context context, Cursor cursor, ViewGroup parent)
Item布局文件的处理 - bindView(View view, Context context, Cursor cursor)
把Cursor获取的数据和布局文件进行绑定
public class MyCursoAdapt extends CursorAdapter {
// 定义布局加载器
private LayoutInflater layoutInflater;
public MyCursoAdapt(Context context, Cursor c) {
super(context, c, 0);
layoutInflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = layoutInflater.inflate(R.layout.list_item,null);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
// 获取到布局的控件
TextView textView = view.findViewById(R.id.item_url);
// 获取Cursor里面的数据
String url = cursor.getString(cursor.getColumnIndex("url"));
// 把数据绑定到控件里面去
textView.setText(url);
}
}
MyCursoAdapt myCursoAdapt = new MyCursoAdapt(this, cursor);
listView.setAdapter(myCursoAdapt);
六、ListView的点击事件
使用setOnItemClickListener() 方法为ListView注册一个监听器,当用
户点击了ListView中的任何一个子项时,就会回调onItemClick()方法。在这个方法中可以通过position参数判断出用户点击的是哪一个子项。
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String string = list.get(position);
Toast.makeText(MainActivity.this,string,1000).show();
}
});