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相当于一个缓存,当有条目变为不可见,它缓存了它的数据,后面再出来的条目只需要更新数据就可以了,这样大大节省了系统资料的开销。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。