android(2)--listView

概览

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的索引修改到对应的数据,并重新刷新界面

ref

1.最简单的listview

posted @ 2020-05-04 19:14  woder  阅读(174)  评论(0编辑  收藏  举报