3

Andorid 开发中我们常常会用到listview这个控件,而listview中如何获取到子item的控件并设置相应事件则相对复杂,并且自定义listview常常需要自定义适配器等等,下面这篇文章将主要介绍如何获取item控件并设置响应事件,主要实现如何点击listview子item中的一个按钮跳转到下一个Activity。废话不多说直接上代码:

主文件:MainActivity(当前Activity)

package com.example.demo_listitem;

import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

public class MainActivity extends Activity {
    private ListView list;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_listview);    
        list=(ListView) findViewById(R.id.listView1)**//找到Listview控件**
        Cadapter ca=new Cadapter(this);**//得到一个Cadapter对象(自定义适配器)**
        list.setAdapter(ca);**//为listview绑定适配器**
    }
**//定义一个得到数据的方法**
    public ArrayList<HashMap<String, Object>> getData() {
        ArrayList<HashMap<String, Object>> listitem=new 
                ArrayList<HashMap<String, Object>>();**//动态数组,装数据**
        for(int i=0;i<20;i++)
        {
            **//利用散列映射添加简单数据**
            HashMap<String, Object> map=new HashMap<String,Object>();
            map.put("title", "hello world");
            listitem.add(map);
        }
        return listitem;**//返回数据源**

    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    
    
}

最重要的地方,自定义适配器:Cadatper(继承自BaseAdapter)
(PS:使用BaseAdapter必须写一个类继承它,同时BaseAdapter是一个抽象类,继承它必须实现它的方法。而最重要的方法就是getView()方法,在此方法内item的绘制(核心的核心),item内控件的寻找,事件的设定都能做。当开始绘制listview时,首先会调用其getCount()方法,得到listview的长度,然后根据这个长度来绘制listview的每一个item)

最重要的重写适配器:Cadapter

package com.example.demo_listitem;

import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView.FindListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class Cadapter extends BaseAdapter{

    private Context context1;
    private LayoutInflater mInflater;
    public Cadapter(Context context)
    {
        context1=context;**//将当前页面的对象赋给context1**
        this.mInflater=LayoutInflater.from(context1);
    }
    @Override
    public int getCount() {
        MainActivity m=new MainActivity();
        return m.getData().size();**//返回listview长度**
        
    }

    @Override
    public Object getItem(int position) {
        return null;
    }
    
    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        
        if(convertView==null)
        {
            **//绘制子item**
            convertView=mInflater.inflate(R.layout.activity_listitem, null);
            **//得到各个控件**
            holder=new ViewHolder();**//存放控件的对象**
            holder.tv=(TextView) convertView.findViewById(R.id.textView1);
            holder.bt=(Button) convertView.findViewById(R.id.button1);
            convertView.setTag(holder); **//将数据和convertView绑定在一起**
        }
        else
        {
            holder=(ViewHolder) convertView.getTag();
        }
        MainActivity m=new MainActivity();
        holder.tv.setText(m.getData().get(position).get("title").toString());**//为item中的Textview设置数据**
      **//按钮的点击事件**
        holder.bt.setOnClickListener(new View.OnClickListener() {        
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent intent=new Intent(context1,NextActivity.class);
                context1.startActivity(intent);
            }
        });
        return convertView;
    }
}

(getview中的代码,其实完全可以不用convertView以及holder,直接加入item布局和设计相应的组件属性就行了,这样做虽然行得通,但只适用于listview中item个数较少的时候可行,当item个数达到1000,10000,1000000就行不通了,因为每个item系统都会绘制一次(getView()一次),item个数较少时还好,当大量的item需要绘制时,会耗费大量的资源在绘制上,这显然实不可取的。
所以,以上代码是经过优化过的,优化之处在于使用convertView和ViewHolder的使用,convertViewconvertView相当于一个缓存,当滑动时,有的条目变为不可见,它缓存了此条目的数据,后面再出来的条目只需要更新数据就可以了,这样大大节省了系统资料的开销
而ViewHolder也是对listview的进一步优化,将holder(找到的控件)用setTag绑定到convertView上,用的时候再用getTag()取出,不用每次都去findviewById,节约系统开销)

下一个页面的Activity:NextActivity

package com.example.deo_listitem;
import android.app.Activity;
import android.os.Bundle;
public class NextActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_next);
    }
}

ViewHolder:

package com.example.demo_listitem;

import android.widget.Button;
import android.widget.TextView;

public final class ViewHolder {
    public TextView tv;
    public Button bt;
}

listvew布局文件:activity_listview

<?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" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

子item布局文件:activity_listitem(就一个textview和一个button)

<?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"
    android:weightSum="1" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:orientation="vertical"
        android:background="#ddc200"
        android:weightSum="1" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:orientation="vertical"
            android:layout_weight="0.5" >

            <TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Medium Text"
                android:textAppearance="?android:attr/textAppearanceMedium" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.5"
            android:orientation="vertical" >

            <Button
                android:id="@+id/button1"
                style="?android:attr/buttonStyleSmall"
                android:layout_width="112dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="下一页" />
        </LinearLayout>

    </LinearLayout>

</LinearLayout>

下一个页面的布局文件:activity_next

<?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"
    android:background="#ddc200" >
</LinearLayout>

convertView原理:当初始显示一屏listview时,convertView的值为空,(因为没有旧的item,旧的指:滑动时移出屏幕的item),当屏幕移动时,有的item滑到屏幕外面,成了旧的item,convertView会回收这些成为旧了的item并缓存起来,如果有新的item产生,则getview()中的convertView就不是空的,而是移出屏幕的item的值(旧item),我们需要做的就是将需要显示的数据填充进去就行了,也就是说convertView相当于一个缓存,当有条目变为不可见,它缓存了它的数据,后面再出来的条目只需要更新数据就可以了,这样大大节省了系统资料的开销。


伊泽瑞尔
215 声望5 粉丝

小小小程序员