ArrayAdapter方式设置listview
利用android自带listview的xml设置简单的listView
思路:MainActivity继承ListActivity,并且在onCreate方法中,首先设置contentView()
在activity_main.xml中有一点奇葩的是设置ListView对象的id为@android:id/list,否则会抛出异常。我们需将ListView的id设置为“@android:id/list”,才可以用getListView来获取ListView的对象。
在代码中的思路如下:
1)使用String数组设置List的item内容
例如:String[] items={“One”, “Two”, “Three”, “Four”, “Five”};
2)在onCreate中将item的内容加入,使用setListAdapter并设置List的格式
setListAdapter(new ArrayAdapter(this,android.R.layout.simple_list_item_1,items));
ArrayAdapter有三个参数,第一是对象,第二是List的格式,第三个是List的内容。对于格式这个例子采用了Android自定义的几种格式 android.R.layout.simple_list_item_1是TextView的方式,采用big font,是最为常见的方式。
3)点击List的Callback方法
由于集成了ListActivity,可以直接使用回调函数onListItemClick
代码如下:
activity.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" tools:context="com.example.mytestlistview.MainActivity" tools:ignore="MergeRootFrame" > <Button android:id="@+id/btn01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="最简单setListAdapter方法" /> <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <!-- 如果不 设置ListView 的id为@android:id/list 就会抛出异常,好奇葩的异常啊 --> </LinearLayout> MainActivity.java package com.example.mytestlistview; import java.util.List; import android.app.ListActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListAdapter; import android.widget.ListView; public class MainActivity extends ListActivity { private String[] items = {"one","two","three","four","five"}; private Button btn; private ListView lv; @SuppressWarnings("unchecked") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button)findViewById(R.id.btn01);//如果没有,则会异常 //最简单listview,没有按钮供选择 //setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,items)); //单选按钮,设置单选listview // setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_single_choice,items)); // getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); //表明有选项,如果不设置,缺省为none,即我们点击后仍无反应 //设置多选listview // setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice ,items)); // getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); //注意,只要点击就会触发Callback,而不过是的点击后选上还是变为取消。 //设置预选选好的多选样式xml // setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_checked,items)); // getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); } public void onListItemClick(ListView lv, View v, int postion, long id) { btn.setText(items[postion]); } @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); } }
利用自定义listview的xml设置简单的listView
首先来一个简单版本的listview,只替换了自定义的item.xml文件,别的没变,思路是在activity_main.xml中定义一个listview,id还是android/list, 接着,定义item.xml代表每一个item应该有的布局,在MainActivity中设置listAdapter 为new的一个ArrayAdapter对象。代码如下:
activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.mytestview.MainActivity" tools:ignore="MergeRootFrame" > <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/btn" android:text="自定义列表" ></Button> <ListView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@android:id/list" ></ListView> </LinearLayout> item.xml //很少代码量,可以丰富这个布局 <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/textview" /> MainActivity.java类 package com.example.mytestview; import java.util.ArrayList; import java.util.List; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.app.ListActivity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListAdapter; import android.widget.ListView; import android.os.Build; public class MainActivity extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //ListView lv = (ListView)findViewById(R.id.lv); // List<String> data = new ArrayList<String>();发现这两种都可以,选择其一就好了... // data.add("测试数据1"); // data.add("测试数据2"); // data.add("测试数据3"); // data.add("测试数据4"); String[] data = {"one","two","three","four","five"}; setListAdapter(new ArrayAdapter(this,R.layout.item,data)); } @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); } }
SimpleAdapter设置ListView
simpleAdapter的扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等。下面的代码都直接继承了ListActivity,ListActivity和普通的Activity没有太大的差别,不同就是对显示ListView做了许多优化,方面显示而已。
很多时候需要在列表中展示一些除了文字以外的东西,比如图片等。这时候可以使用SimpleAdapter。SimpleAdapter的使用也非常简单,同时它的功能也非常强大。可以通过它自定义ListView中的item的内容,比如图片、多选框等。
方法和上面使用ArrayAdapter差不多,不过更多内容可以定制,在xml中添加了如下布局
Title image
text image
作为一栏,其中image是一整张图片,而不是两个图片.
注意这里MainActivity类继承的是Activity类,而不是ListActivity,否则会报错!!!
原因是如果只是想用List,而不使用别的元素布局,则使用ListActivity,但是如果想用别的页面布局,元素布局,则一定要用Activity(Activity方法首先setContentView(xxx); listview = findViewById(xxxx), 然后listview.setAdapter(); 完事。 然而,ListActivity首先是设置adapter,然后用setListAdapter()就可以设置页面布局,只需要一个item.xml就可以了!)
使用simpleAdapter的数据一般都是用HashMap构成的列表,列表的每一节对应ListView的每一行。通过SimpleAdapter的构造函数,将HashMap的每个键的数据映射到布局文件中对应控件上。这个布局文件一般根据自己的需要来自己定义。梳理一下使用SimpleAdapter的步骤。
(1)根据需要定义ListView每行所实现的布局。
(2)定义一个HashMap构成的列表,将数据以键值对的方式存放在里面。
(3)构造SimpleAdapter对象。
(4)将LsitView绑定到SimpleAdapter上。
item.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="fill_parent" android:layout_width="fill_parent"> <ImageView android:layout_alignParentRight="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ItemImage"/> <TextView android:id="@+id/ItemTitle" android:layout_height="wrap_content" android:layout_width="fill_parent" android:textSize="20sp"/> <TextView android:id="@+id/ItemText" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_below="@+id/ItemTitle"/> </RelativeLayout> activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.mytestview.MainActivity" tools:ignore="MergeRootFrame" > <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/btn" android:text="自定义列表" ></Button> <ListView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/listview" ></ListView> </LinearLayout> MainActivity.Java package com.example.mytestview; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.app.Activity; import android.app.ListActivity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ListAdapter; import android.widget.ListView; import android.os.Build; import android.widget.SimpleAdapter; public class MainActivity extends Activity { private ListView lv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv = (ListView)findViewById(R.id.listview); ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String,Object>>();/*在数组中存放数据*/ for(int i=0;i<10;i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("ItemImage", R.drawable.icon);//加入图片 map.put("ItemTitle", "第"+i+"行"); map.put("ItemText", "这是第"+i+"行"); listItem.add(map); } ////需要绑定的数据 ////每一行的布局//动态数组中的数据源的键对应到定义布局的View中 SimpleAdapter mSimpleAdapter = new SimpleAdapter(this,listItem,R.layout.item,new String[] {"ItemImage","ItemTitle", "ItemText"}, new int[]{R.id.ItemImage,R.id.ItemTitle,R.id.ItemText} ); lv.setAdapter(mSimpleAdapter);//为ListView绑定适配器 lv.setOnItemClickListener(new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { setTitle("你点击了第"+arg2+"行");//掌握了一个新方法设置当前对话框的题目啊!!!激动 } }); } @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); } }
继承BaseAdapter
给ListView添加按钮操作事件
有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮。添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配器,然后将数据映射到布局文件上。但是事实并非这样,因为按钮是无法映射的,即使你成功的用布局文件显示出了按钮也无法添加按钮的响应,这时就要研究一下ListView是如何现实的了,而且必须要重写一个类继承BaseAdapter,并告诉你ListView究竟是如何工作的。
vlist2.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5px"/> <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#FFFFFFFF" android:textSize="22px" /> <TextView android:id="@+id/info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#FFFFFFFF" android:textSize="13px" /> </LinearLayout> <Button android:id="@+id/view_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right" android:text="哇哈哈" /> </LinearLayout>
MainActivity.java文件
package com.example.mytestview; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.app.AlertDialog; import android.app.ListActivity; import android.content.Context; import android.content.DialogInterface; import android.database.Cursor; import android.os.Bundle; import android.provider.Contacts.People; import android.support.v4.widget.SimpleCursorAdapter; import android.util.Log; 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.ListAdapter; import android.widget.ListView; import android.widget.TextView; @SuppressWarnings("deprecation") public class MainActivity extends ListActivity { private List<Map<String, Object>> mData; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mData = getData(); MyAdapter adapter = new MyAdapter(this); setListAdapter(adapter); } private List<Map<String, Object>> getData() { List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); Map<String, Object> map = new HashMap<String, Object>(); map.put("title", "G1"); map.put("info", "google 1"); map.put("img", R.drawable.icon); list.add(map); map = new HashMap<String, Object>(); map.put("title", "G2"); map.put("info", "google 2"); map.put("img", R.drawable.icon); list.add(map); map = new HashMap<String, Object>(); map.put("title", "G3"); map.put("info", "google 3"); map.put("img", R.drawable.icon); list.add(map); return list; } // ListView 中某项被选中后的逻辑 protected void onListItemClick(ListView l, View v, int position, long id) { Log.v("MyListView4-click", (String)mData.get(position).get("title")); } /** * listview中点击按键弹出对话框 */ public void showInfo(){ new AlertDialog.Builder(this) .setTitle("我的listview") .setMessage("介绍...") .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }) .show(); } public final class ViewHolder{ public ImageView img; public TextView title; public TextView info; public Button viewBtn; } public class MyAdapter extends BaseAdapter{ private LayoutInflater mInflater; public MyAdapter(Context context){ this.mInflater = LayoutInflater.from(context); } @Override public int getCount() { // TODO Auto-generated method stub return mData.size(); } @Override public Object getItem(int arg0) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder=new ViewHolder(); convertView = mInflater.inflate(R.layout.vlist2, null); holder.img = (ImageView)convertView.findViewById(R.id.img); holder.title = (TextView)convertView.findViewById(R.id.title); holder.info = (TextView)convertView.findViewById(R.id.info); holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn); convertView.setTag(holder);//绑定ViewHolder对象 }else { holder = (ViewHolder)convertView.getTag();//取出ViewHolder对象 } holder.img.setBackgroundResource((Integer)mData.get(position).get("img")); holder.title.setText((String)mData.get(position).get("title")); holder.info.setText((String)mData.get(position).get("info")); holder.viewBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showInfo(); } }); return convertView; } } }
下面将对上述代码,做详细的解释,listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示。同样,return 1,就只显示一行。
系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。
当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。
但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了。
现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那 再绘制下一行,直到绘完为止。
SimpleCursorAdapter
sdk的解释是这样的:An easy adapter to map columns from a cursor to TextViews or ImageViews defined in an XML file. You can specify which columns you want, which views you want to display the columns, and the XML file that defines the appearance of these views。简单的说就是方便把从游标得到的数据进行列表显示,并可以把指定的列映射到对应的TextView中。
下面的程序是从电话簿中把联系人显示到类表中。先在通讯录中添加一个联系人作为数据库的数据。然后获得一个指向数据库的Cursor并且定义一个布局文件(当然也可以使用系统自带的)。
package com.example.mytestview; import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.provider.Contacts.People; import android.support.v4.widget.SimpleCursorAdapter; import android.widget.ListAdapter; import android.widget.ListView; @SuppressWarnings("deprecation") public class MainActivity extends Activity { private ListView listView; //private List<String> data = new ArrayList<String>(); @SuppressWarnings("deprecation") @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); listView = new ListView(this); //先获得一个指向系统通讯录数据库的Cursor对象获得数据来源。 Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null); //们将获得的Cursor对象交由Activity管理,这样Cursor的生命周期和Activity便能够自动同步,省去自己手动管理Cursor。 startManagingCursor(cursor); ListAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1, cursor,//下面两个参数,一个包含数据库的列的String型数组,一个包含布局文件中对应组件id的int型数组。其作用是自动的将String型数组所表示的每一列数据映射到布局文件对应id的组件上 new String[]{People.NAME}, new int[]{android.R.id.text1}); //将NAME列的数据一次映射到布局文件的id为text1的组件上。 listView.setAdapter(listAdapter); setContentView(listView); } }