概览
1.listview只是作为一个容器,其中的每一个view都是在代码中生成,而不是写死在listview.xml中
2.每个view是通过实现一个adapter中重写getview()接口,在其中使用inflate()去动态生成的
3.要为每个view添加相应的按钮的话,可以实现一个继承了View.OnClickListener的类,在其中重写onClick方法,每次getView更新view对象的时候将view的button绑定到该listener中,并把postion放在这个listener里面用于索引数据
正文
一下皆为从正式代码中抽写出来的精简版本,可能有错会运行不了
1.1一个简单的listView
这一块前人已经写好了代码,详见ref1, 下面抽象一个简单的
首先是main布局文件, 引入了一个listview的layout
<!-- 文件:activity_main.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"
android:orientation="vertical" >
<!-- 中间 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
<!-- 引入了一个listview的layout-->
<include layout="@layout/listviewon1" />
</LinearLayout>
</LinearLayout>
listview的layout如下:
<!-- 文件:listviewon1-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>
然后在代码中加载整个activity_main之后,就需要设置一个adapter去生成listview中的view了
public class MainActivity extends AppCompatActivity {
private String[] data ={"东北虎","野猪","野牛","狗熊","狐狸","猴子"};
private MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载activity_main
setContentView(R.layout.activity_main);
//设置一个adapter,用于创建listview中的view
myAdapter = new MyAdapter(this, data);
//设置adapter
ListView listView = (ListView) findViewById(R.id.listView1);
listView.setAdapter(adapter);
}
}
adapter是用来提供数据和生成view的,这些动作发生在其重写了getView()接口内, 使用了R.layout.listviewitems创建了一个view对象,并从中获取该view对象的TextView
public class MyAdapter extends BaseAdapter{
private int resourceId;
private string [] data;
private LayoutInflater mInflater;
public MyAdapter(Context context, String[] data) {
this.data = data;
this.mInflater = LayoutInflater.from(context);
}
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
MyListener myListener=null;
String animal = data[position];
if(convertView == null){
view = mInflater.inflate(R.layout.listviewitems, null);
Log.i("info:", "没有缓存,重新生成"+position+"对象的hash code: "+ view.hashCode()+" 当前对象数: "+i);
}else{
Log.i("info:", "有缓存,不需要重新生成"+position+" 对象的hash code: "+convertView.hashCode());
view = convertView;
}
//获取组件
TextView tv_animal = (TextView)view.findViewById(R.id.animal);
tv_animal.setText(animal);
return view;
}
其中listviewitems的布局文件如下:
<?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="horizontal" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="1"
android:gravity="center|center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/animal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="animal" />
</LinearLayout>
</LinearLayout>
1.2 为每个view添加按钮
时常需要为每个listview中的view添加按钮,通过这个按钮去修改当前view对象中的object数据,但是我们知道listview其实只是创建了一页的view对象,这个view对象是一直循环使用的,所以我们需要在每次做getView的时候为每一个button对象做一个重新对应到对应object数据的的操作, 一个例子如下:
public View getView(int position, View convertView, ViewGroup parent) {
//TODO lock updateViewLock 为了防止timeupdate更新数据时而此处异步更新了区间
//布局不变,数据变
View view = null;
MyListener myListener=null;
String animal = data[position];
if(convertView == null){
Log.i("info:", "没有缓存,重新生成"+position+"对象的hash code: "+ view.hashCode()+" 当前对象数: "+i);
view = mInflater.inflate(R.layout.listviewitems, null);
myListener = new MyListener(position);
view.setTag(myListener);
}else{
Log.i("info:", "有缓存,不需要重新生成"+position+" 对象的hash code: "+convertView.hashCode());
myListener = (MyListener)convertView.getTag();
myListener.mPosition = position;
view = convertView;
}
//获取组件
Button startButton = (Button)view.findViewById(R.id.startButton);
Button finishButton = (Button)view.findViewById(R.id.startButton);
TextView tv_animal = (TextView)view.findViewById(R.id.animal);
//更新button的对应的数据
tv_animal.setText(animal);
startButton.setOnClickListener(myListener);
finishButton.setOnClickListener(myListener);
return view;
}
private class MyListener implements View.OnClickListener {
int mPosition;
public MyListener(int inPosition){
mPosition= inPosition;
}
@Override
public void onClick(View v) {
if(v.getId() == R.id.startButton)
data[mPosition] = "start";
else if(v.getId() == R.id.finishButton)
data[mPosition] = "finish";
//重新刷新界面
notifyDataSetChanged();
}
}
可以看到每次当每个view进行数据刷新显示别的对象数据的时候,通过将position保存在mylistener中,然后重新将button绑定在该listener中,当触发了onClick之后就可以顺利的通过这个postion的索引修改到对应的数据,并重新刷新界面