利用ListView和Arrayader实现一个带有图片和介绍的列表:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//use ArrayAdapter
lv_list = (ListView) findViewById(R.id.lv_list);
initDataList();
Log.e(TAG, "will new adapter");
adapter = new MyAdapter(this, R.layout.list_item, datalist);
//adapter = new MyAdapter(this, R.layout.list_item, 0);
Log.e(TAG, "new adapter done");
lv_list.setAdapter(adapter);
}
private void initDataList() {
datalist = new ArrayList<>();
for (int i = 1; i < 10; i++){
Fruit fruit = new Fruit();
fruit.imgId = R.drawable.adc;
fruit.name = "lyl" + i;
datalist.add(fruit);
}
}
class MyAdapter extends ArrayAdapter<Fruit>{
private int resourceId;
private Context myContext;
private ViewHolder holder;
// public MyAdapter(Context context, int resource, int textViewResourceId) {
// super(context, resource, textViewResourceId);
// resourceId = resource;
// }
public MyAdapter(Context context, int textViewResourceId, List<Fruit> objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
myContext = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Fruit fruit = getItem(position);
//Fruit fruit = datalist.get(position);//二者相同
if (null == convertView){
convertView = LayoutInflater.from(myContext).inflate(resourceId, parent, false);
/*
参3为false,只让在父布局声明的Layout属性生效,并不会为这个View添加父布局。
因为View一旦有了父布局之后,就不能添加到ListView中了
*/
holder = new ViewHolder();
holder.tv_list = convertView.findViewById(R.id.tv_list);
holder.iv_list = convertView.findViewById(R.id.iv_list);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.iv_list.setImageResource(fruit.imgId);
holder.tv_list.setText(fruit.name);
return convertView;
}
}
class ViewHolder{
ImageView iv_list;
TextView tv_list;
}
class Fruit{
int imgId;
String name;
}
list_item.xml布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/ic_launcher"
android:layout_margin="10dp"
android:id="@+id/iv_list"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="name"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:textSize="20sp"
android:id="@+id/tv_list"/>
</LinearLayout>
代码比较简单,可是在实现getView()方法时,发现
Fruit fruit = getItem(position);
Fruit fruit1 = datalist.get(position);
二者是同一个对象,就跟了下源码。
大家都比较熟悉的就是,继承了BaseAdapter,要实现以下四个方法
public int getCount() ;
public Object getItem(int position) ;
public long getItemId(int position);
public View getView(int position, View convertView, ViewGroup parent);
很显然,ArrayAdapter继承自BaseAdapter
public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {}
也要实现以上四种方法
@Override
public int getCount() {
return mObjects.size();
}
@Override
public @Nullable T getItem(int position) {
return mObjects.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public @NonNull View getView(int position, @Nullable View convertView,
@NonNull ViewGroup parent) {
return createViewFromResource(mInflater, position, convertView, parent, mResource);
}
getItem()方法, 返回了mObjects.get(position); 很自然的联想到datalist.get(position),但mObjects是如何赋值的?通过源码可以查知
private ArrayAdapter(@NonNull Context context, @LayoutRes int resource,
@IdRes int textViewResourceId, @NonNull List<T> objects, boolean objsFromResources) {
mContext = context;
mInflater = LayoutInflater.from(context);
mResource = mDropDownResource = resource;
mObjects = objects;
mObjectsFromResources = objsFromResources;
mFieldId = textViewResourceId;
}
public ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects) {
this(context, resource, textViewResourceId, objects, false);
}
public ArrayAdapter(Context context, int resource, List<T> objects) {
this(context, resource, 0, objects);
}
public MyAdapter(Context context, int textViewResourceId, List<Fruit> objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
myContext = context;
}
adapter = new MyAdapter(this, R.layout.list_item, datalist);
就是datalist传值给mObjects的。所以在getView()方法中
Fruit fruit = getItem(position);
Fruit fruit1 = datalist.get(position);
二者相同。
但是调用ArrayAdapter的其他构造器,如
public MyAdapter(Context context, int resource, int textViewResourceId)
mObjects为null,但并未调用重写的getView()方法,不知为何,虽然该例子中没有textViewResourceId,且该值置为了0.
链接:inflate方法