ListActivity可以理解为是ListView和Activity的结合。主要用来显示列表数据。显示数据需要设置适配器。Adapter常用的有ArrayAdapter,SimpleAdapter和CursorAdapter。
ListActivity的使用步骤:1)继承自ListActivity,如:xxx extends ListActivity
2)重写onCreate方法,在该方法中,需要做三件事情:
a)准备数据源
b)设置适配器
c)绑定适配器
3)重写点击事件void onListItemClick(ListView l, View v, int position, long id)
下面分情况来讲解各种使用方法:
1.使用默认的样式显示一行文本
代码如下:
import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
/**
* Created by wangwentao on 2017/2/3.
* 说明:使用默认的布局显示一行文本
*/
public class ListActivityOne extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//1.数据源
String[] data = {"老师","学生","课桌","书本","铅笔","橡皮","粉笔","黑板","凳子","扫帚","簸箕","炉子","窗花","讲台","教鞭","小红花","花瓶"};
//2.适配器
@SuppressWarnings("unchecked")
ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, data);
//3.绑定
setListAdapter(arrayAdapter);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Toast.makeText(ListActivityOne.this,"点中了第"+id+"个",Toast.LENGTH_LONG).show();
}
}
解析:常见的显示样式包括以下几种
android.R.layout.simple_list_item_1 一行text ;
android.R.layout.simple_list_item_2 一行title,一行text ;
android.R.layout.simple_list_item_single_choice 单选按钮
android.R.layout.simple_list_item_multiple_choice 多选按钮
android.R.layout.simple_list_item_checked checkbox
ArrayAdapter用于显示比较简单的样式,SimpleAdapter用于显示相对较复杂的样式.
下面讲一下
void onListItemClick(ListView l, View v, int position, long id)中的参数:
前两个参数比较好理解,主要是后面两个,int position指的是ListView中的View的位置,long id是被点击组件的行id或者可以理解为数据源的id
需要注意:并不是所有情况下postion和id的值都是相等
2.使用默认样式显示两行文本代码如下:
解析:使用android.R.layout.simple_list_item_2显示两行文本,用到的是SimpleAdapter适配器,下面讲一下SimpleAdapter的使用import android.app.ListActivity; import android.os.Bundle; import android.view.View; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; /** * Created by wangwentao on 2017/2/3. */ public class ListActivityTwo extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //1.数据源 List listData = this.getData(); //2.适配器 @SuppressWarnings("unchecked") SimpleAdapter simpleAdapter = new SimpleAdapter(this, listData, android.R.layout.simple_list_item_2, new String[] {"name", "desc"}, new int[] {android.R.id.text1, android.R.id.text2}); //3.绑定 setListAdapter(simpleAdapter); } //获取显示的数据 private List getData() { List retList = new ArrayList(); for(int index = 0; index < 50; ++index){ Hashtable table = new Hashtable(); table.put("name", "name"+index); table.put("desc", "desc"+index); retList.add(table); } return retList; } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Toast.makeText(ListActivityTwo.this,"position:"+position+";id:"+id,Toast.LENGTH_LONG).show(); } }
SimpleAdapter(Context context, List> data, int resource, String[] from, int[] to) 其中: context : 当前的环境上下文,一般直接传递this就OK Data:数据源,我们之前构造的listData就是该ListView的数据源 resource:layout模板资源,我们可以传递Android自带的,当然也可以自定义,我们在这里为了简单传递的是Android自带的 from和to:这个我们需要联合起来看,这两个是平行数组,也就是数组的大小相同,根据我们的例子,我们需要在android.R.id.text1中显示数据源中索引为”name”的项,在android.R.id.text2种显示索引为”desc”的项。
3.使用默认样式显示单选按钮
代码如下:
import android.app.ListActivity; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; /** * Created by wangwentao on 2017/2/3. * 说明:使用默认样式显示单选按钮 */ public class ListActivityThree extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //1.数据源 String[] data = new String[] {"老师","学生","课桌","书本","铅笔","橡皮","粉笔","黑板","凳子","扫帚","簸箕","炉子","窗花","讲台","教鞭","小红花","花瓶"}; //2.适配器 ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(ListActivityThree.this,android.R.layout.simple_list_item_single_choice,data); //设置ListView的属性 ListView listView = this.getListView(); listView.setItemsCanFocus(false); listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); //3.绑定 setListAdapter(arrayAdapter); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Toast.makeText(ListActivityThree.this,"position:"+position+";id:"+id,Toast.LENGTH_LONG).show(); } }
解析:需要设置ListActivity中内置的ListView的选择模式,不然出现的效果就是可以点中,但是看不到点中的圆圈的点中的效果
4.使用默认样式显示单选框
代码如下:
import android.app.ListActivity; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; /** * Created by wangwentao on 2017/2/3. */ public class ListActivityFour extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //1.数据源 String[] data = new String[] {"老师","学生","课桌","书本","铅笔","橡皮","粉笔","黑板","凳子","扫帚","簸箕","炉子","窗花","讲台","教鞭","小红花","花瓶"}; //2.适配器 ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(ListActivityFour.this,android.R.layout.simple_list_item_checked,data); //设置ListView的属性 ListView listView = this.getListView(); listView.setItemsCanFocus(false); listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); //3.绑定 setListAdapter(arrayAdapter); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Toast.makeText(ListActivityFour.this,"position:"+position+";id:"+id,Toast.LENGTH_LONG).show(); } }
5.使用默认样式显示多选框
代码如下:
import android.app.ListActivity; import android.os.Bundle; import android.util.Log; import android.util.SparseBooleanArray; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; /** * Created by wangwentao on 2017/2/3. * 说明:使用默认样式显示多选框 */ public class ListActivityFive extends ListActivity { public static final String TAG = "当前选中的项为:"; ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //1.数据源 String[] data = new String[] {"老师","学生","课桌","书本","铅笔","橡皮","粉笔","黑板","凳子","扫帚","簸箕","炉子","窗花","讲台","教鞭","小红花","花瓶"}; //2.适配器 ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(ListActivityFive.this,android.R.layout.simple_list_item_multiple_choice,data); //设置ListView的属性 listView = this.getListView(); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); //3.绑定 setListAdapter(arrayAdapter); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); SparseBooleanArray checkedItems = listView.getCheckedItemPositions(); Log.i("打印选中项开始","-------------------------------------------------------------"); for (int i = 0; i < checkedItems.size(); ++i){ if(checkedItems.valueAt(i)==true){//表示第i个元素被选中 Log.i(TAG,i+""); } } Log.i("打印选中项结束","-------------------------------------------------------------"); } }
输出的日志:
02-03 00:03:15.334 11863-11863/com.mobile.cdtx.blog I/打印选中项开始: ------------------------------------------------------------- 02-03 00:03:15.334 11863-11863/com.mobile.cdtx.blog I/当前选中的项为:: 0 02-03 00:03:15.334 11863-11863/com.mobile.cdtx.blog I/打印选中项结束: ------------------------------------------------------------- 02-03 00:03:17.687 11863-11863/com.mobile.cdtx.blog I/打印选中项开始: ------------------------------------------------------------- 02-03 00:03:17.687 11863-11863/com.mobile.cdtx.blog I/当前选中的项为:: 0 02-03 00:03:17.687 11863-11863/com.mobile.cdtx.blog I/当前选中的项为:: 1 02-03 00:03:17.687 11863-11863/com.mobile.cdtx.blog I/打印选中项结束: ------------------------------------------------------------- 02-03 00:03:19.725 11863-11863/com.mobile.cdtx.blog I/打印选中项开始: ------------------------------------------------------------- 02-03 00:03:19.726 11863-11863/com.mobile.cdtx.blog I/当前选中的项为:: 0 02-03 00:03:19.726 11863-11863/com.mobile.cdtx.blog I/当前选中的项为:: 1 02-03 00:03:19.726 11863-11863/com.mobile.cdtx.blog I/当前选中的项为:: 2 02-03 00:03:19.726 11863-11863/com.mobile.cdtx.blog I/打印选中项结束: -------------------------------------------------------------
解析:SparseBooleanArray中存放的是key,value,key是选中的索引,value的值如果为true表示表中,如果为false表示未选中
6.使用自定义布局
ListActivity除了可以使用默认的布局外,还可以自定义布局,通过在onCreate()里面调用setContentView(resources id)。不过要注意:在自定义的Layout里面,必须包括一个(只能一个)ListView,而且要设置ListView对象的id为"@android :id/list",不能随便自定义id;在这个layout.xml文件中还可以添加其他的widget。在Java代码里使用android.R.id.list。
如果当ListView中没有值而又想提示一句话时,那么用于指定显示提示信息的TextView的 id 必须为 "@android :id/empty",当ListView里面没有data的时候,就会显示。
代码如下:
activity_list_custom.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"> <ListView android:id="@id/android:list" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <TextView android:id="@id/android:empty" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="没有数据" /> <Button android:id="@+id/btn_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="点击切换ListView是否有数据" /> </LinearLayout>
java代码如下:import android.app.ListActivity; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.Toast; /** * Created by wangwentao on 2017/2/3. * 说明: */ public class ListActivitySix extends ListActivity { private boolean bData = true;//true表示默认显示数据,false表示没有数据 private String[] data; ArrayAdapter<String> arrayAdapter; private String[] noData; ArrayAdapter<String> arrayAdapterNoData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list_custom); //初始化View initView(); //1.数据源 data = new String[] {"老师","学生","课桌","书本","铅笔","橡皮","粉笔","黑板","凳子","扫帚","簸箕","炉子","窗花","讲台","教鞭","小红花","花瓶"}; noData = new String[]{}; //2.适配器 arrayAdapter = new ArrayAdapter<String>(ListActivitySix.this,android.R.layout.simple_list_item_1,data); arrayAdapterNoData = new ArrayAdapter<String>(ListActivitySix.this,android.R.layout.simple_list_item_1,noData); //3.绑定 setListAdapter(arrayAdapter); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Toast.makeText(ListActivitySix.this,"点中了第"+id+"个",Toast.LENGTH_LONG).show(); } //初始化View private void initView(){ Button btnData = (Button)findViewById(R.id.btn_data); btnData.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { if(bData){ setListAdapter(arrayAdapterNoData); }else{ setListAdapter(arrayAdapter); } bData = !bData; } }); } }
7.使用自定义ListItem 除了可以使用系统自带的样式外,还可以使用自定义样式.代码如下:
list_item_custom.xml
java代码如下:<?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="match_parent" android:descendantFocusability="blocksDescendants"> <ImageView android:id="@+id/imageV" android:layout_marginLeft="5dp" android:layout_width="46dp" android:layout_height="46dp" android:contentDescription="" android:src="@mipmap/ic_launcher" /> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginLeft="10dp" android:orientation="vertical"> <TextView android:id="@+id/text_title" android:layout_marginTop="2dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="14sp" /> <TextView android:id="@+id/text_content" android:layout_marginTop="5dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="12sp" /> </LinearLayout> <Button android:id="@+id/btn" android:focusable="false" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮"/> </LinearLayout>
import android.app.ListActivity; import android.os.Bundle; import android.view.View; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; import com.mobile.cdtx.blog.R; import java.util.ArrayList; import java.util.HashMap; /** * Created by wangwentao on 2017/2/3. * 说明:使用自定义样式 */ public class ListActivitySeven extends ListActivity { private ArrayList<HashMap<String, Object>> dataItems;//存放数据信息 private SimpleAdapter simpleListAdapter;//适配器 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //1.数据源 initData(); //2.适配器 initAdapter(); //3.绑定 setListAdapter(simpleListAdapter); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Toast.makeText(ListActivitySeven.this,"点中了第"+id+"个",Toast.LENGTH_LONG).show(); } //构建数据 private void initData(){ dataItems = new ArrayList<HashMap<String, Object>>(); for(int i=0;i<20;i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("image", R.mipmap.ic_launcher);//图标 map.put("title", "标题"+i);//标题 map.put("content", "内容"+i);//内容 dataItems.add(map); } } //构建适配器 private void initAdapter(){ simpleListAdapter = new SimpleAdapter(this,dataItems, //数据源 R.layout.list_item_custom, //每一行显示数据布局 new String[] {"image", "title","content"},//动态数组对应的子项 new int[ ] {R.id.imageV, R.id.text_title,R.id.text_content} //每一行布局文件里面对应的三个控件的id ); } }
解析:每一行显示三个元素:图标,标题,内容如果数据源比较大,不要在UI线程中进行绑定数据,否则会造成卡死;这种情况最好是在多线程中绑定数据。
常用的方法有:
1)Activity.runOnUiThread(Runnable)
2)View.post(Runnable)
3)Handler+Thread
4)AsyncTask
上面演示的自定义布局中文件中有Button控件,正常情况下listitem的点击和button的点击事件会产生冲突,上面采用的是在xml文件中
对每一行的布局设置属性android:descendantFocusability="blocksDescendants",对于Button控件设置属性android:focusable="false"来解决冲突的
如果要想给每一行的ListItem中的Button单独设置点击事件,需要自定义适配器,关键是重写public View getView(int position, View convertView, ViewGroup parent)这个方法。
代码如下:
list_item_custom.xml文件如上,没有变化
自定义适配器代码如下:
import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.mobile.cdtx.blog.R; import java.util.ArrayList; import java.util.HashMap; /** * Created by wangwentao on 2017/2/3. */ public class CustomAdapter extends BaseAdapter { private ArrayList<HashMap<String, Object>> dataItems; private Context context; private LayoutInflater mInflater; public CustomAdapter(Context context,ArrayList<HashMap<String, Object>> dataItems) { this.context=context; this.mInflater=LayoutInflater.from(context); this.dataItems = dataItems; } @Override public int getCount() { return dataItems.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; final int pos = position; if(null == convertView) { convertView=mInflater.inflate(R.layout.list_item_custom, null); holder=new ViewHolder(); holder.imageView = (ImageView) convertView.findViewById(R.id.imageV); holder.title=(TextView) convertView.findViewById(R.id.text_title); holder.content=(TextView) convertView.findViewById(R.id.text_content); holder.btn=(Button) convertView.findViewById(R.id.btn); convertView.setTag(holder); }else { holder=(ViewHolder) convertView.getTag(); } //设置数据 holder.imageView.setImageResource(R.mipmap.ic_launcher); holder.title.setText(dataItems.get(position).get("title").toString()); holder.content.setText(dataItems.get(position).get("content").toString()); holder.btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context,"点中了第"+pos+"行的按钮",Toast.LENGTH_LONG).show(); } }); return convertView; } class ViewHolder { public ImageView imageView; public TextView title; public TextView content; public Button btn; } }
界面显示的代码如下:解析:这里使用了自定义适配器,关键是在gertView中设置数据和点击事件,同时解决了ListItem点击事件和子项点击事件冲突的问题。import android.app.ListActivity; import android.os.Bundle; import android.view.View; import android.widget.ListView; import android.widget.Toast; import com.mobile.cdtx.blog.R; import com.mobile.cdtx.blog.activity.adapter.CustomAdapter; import java.util.ArrayList; import java.util.HashMap; /** * Created by wangwentao on 2017/2/3. * 说明:使用自定义样式,自定义适配器 */ public class ListActivitySeven extends ListActivity { private ArrayList<HashMap<String, Object>> dataItems;//存放数据信息 private CustomAdapter customAdapter;//自定义适配器 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //1.数据源 initData(); //2.适配器 customAdapter = new CustomAdapter(ListActivitySeven.this,dataItems); //3.绑定 setListAdapter(customAdapter); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Toast.makeText(ListActivitySeven.this,"点中了第"+id+"个",Toast.LENGTH_LONG).show(); } //构建数据 private void initData(){ dataItems = new ArrayList<HashMap<String, Object>>(); for(int i=0;i<20;i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("image", R.mipmap.ic_launcher);//图标 map.put("title", "标题"+i);//标题 map.put("content", "内容"+i);//内容 dataItems.add(map); } } }