Android学习 —— 多种适配器方式实现ListView
笔记摘要:
本文主要对ListView列表显示的实现进行了分析,对于列表显示,分为两个部分,第一个部分是整体布局,也就是ListView所在的布局,但ListView中的一个个横条Item布局也需要我们自己去构建,所以需要创建一个Item的布局文件,然后通过配置器来引入,当然也引入一些数据,最后为ListView设置适配器即可。适配器有多种,这里就介绍了几种不同的适配器:ArrayAdapter、SimpleAdapter、CursorAdapter、以及自定义的Adapter。
ArrayAdapter
ArrayAdapter的使用比较简单,只需为ListView设置ArrayAdapter,然后传入要显示的内容即可。由名字也可以看出,是一个类似于数组的形式,所以条目都统一了样式,
比较单一,传值也比较简便。
main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <ListView android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
条目显示布局:listview_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:gravity="center_vertical" android:layout_height="wrap_content" android:orientation="horizontal" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/btn_rating_star_on_normal_holo_light" /> <TextView android:id="@+id/tv_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是文本" android:textSize="24sp" /> </LinearLayout>
import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.SimpleAdapter; public class MainActivity extends Activity { ListView lv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv = (ListView) findViewById(R.id.listView_id); lv.setAdapter(new ArrayAdapter(this,R.layout.listview_item, R.id.tv_content,new String[]{"功能1","功能2","功能3"})); } }
SimpleAdatper
构造函数:
SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
由SimpleAdapter的构造函数列表可以看出,
List<? extends Map<String, ?>>需要一个存储Map集合的List集合,来提供数据
int resource:一个布局文件来提供页面布局
From:A list of column names that will be added to the Map associated with each item.,需要适配数据的列名,其与Map集合的键相对应。
To : The views that should display column in the "from" parameter. These should all be TextViews. 与From相对应的TextView的资源ID
整体布局文件Main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <TextView android:id="@+id/info_textView" android:text="产品详细信息" android:textSize="25sp" android:gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content" /> <ListView android:layout_below="@id/info_textView" android:id="@+id/listView_id" android:layout_width="match_parent" android:layout_height="match_parent" ></ListView> </RelativeLayout>
条目的布局文件listView_item.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="horizontal" > <TextView android:id="@+id/model_textView" android:text="型号" android:textSize="20sp" android:gravity="center_horizontal" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:text="颜色" android:textSize="20sp" android:gravity="center_horizontal" android:layout_weight="1" android:id="@+id/color_textView" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:text="大小" android:textSize="20sp" android:layout_weight="1" android:gravity="center_horizontal" android:id="@+id/size_textView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.ListView; import android.widget.SimpleAdapter; public class MainActivity extends Activity { private ListView listView; private List<Map<String,String>> data ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView_id); Map<String,String> itemdata1 = new HashMap<String,String>(); itemdata1.put("型号","复古"); itemdata1.put("颜色","浅灰"); itemdata1.put("大小","Large"); Map<String,String> itemdata2 = new HashMap<String,String>(); itemdata2.put("型号","时尚"); itemdata2.put("颜色","紫金"); itemdata2.put("大小","small"); data = new ArrayList<Map<String,String>>(); data.add(itemdata1); data.add(itemdata2); //SimpleAdapter(Context context, List<? extends Map<String,?>> data, int resource, String[] from, int[] to) //context,上下文 //List<? extends Map<String, ?>> data,提供要显示的数据 //int resource,一个布局文件来提供页面布局 //String[] from, 需要适配数据的列名,其与Map集合的键相对应。 //int[] to 与from相对应的显示视图,必须都是TextView,通过R.id.TextView来引入 listView.setAdapter(new SimpleAdapter(this, data, R.layout.listview_item, new String[]{"颜色","型号","大小"}, new int[]{R.id.model_textView,R.id.color_textView,R.id.size_textView})); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
CursorAdapter
注意:
在使用CursorAdapter为Listview适配的时候,Sqlite标准要求cursor必须有一个属性 "_id",否则就无法使用
在使用SimpleCursorAdapter时,有一个相同的方法已经过时,对于这样的处理,为了向下兼容,我们可以将低版本和高版本的方法都提供出 去,只需对用户的版本进行判断调用响应的方法即可
总体布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" 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:orientation="horizontal" > <TextView android:text="姓名" android:textSize="23sp" android:id="@+id/name_textView" android:layout_weight="1" android:layout_gravity="center_horizontal" android:gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="电话" android:textSize="23sp" android:id="@+id/phone_textView" android:layout_weight="1" android:gravity="center" android:layout_gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="收入" android:textSize="23sp" android:id="@+id/money_textView" android:layout_weight="1" android:gravity="center" android:layout_gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <ListView android:id="@+id/listView_id" android:layout_width="match_parent" android:layout_height="match_parent" ></ListView> </LinearLayout>
条目布局文件
<?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" > <TextView android:text="姓名" android:id="@+id/name_textView" android:textSize="20sp" android:layout_weight="1" android:layout_gravity="center_horizontal" android:gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="电话" android:id="@+id/phone_textView" android:textSize="20sp" android:layout_weight="1" android:gravity="center" android:layout_gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="收入" android:id="@+id/money_textView" android:textSize="20sp" android:layout_weight="1" android:gravity="center" android:layout_gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
MainActivity
import android.app.Activity; import android.database.Cursor; import android.os.Build; import android.os.Bundle; import android.support.v4.widget.CursorAdapter; import android.support.v4.widget.SimpleCursorAdapter; import android.util.Log; import android.webkit.WebChromeClient.CustomViewCallback; import android.widget.LinearLayout; import android.widget.ListView; import com.itheima.db.dao.PersonDao2; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private ListView listView; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView_id); /*PersonDBOpenHelper helper = new PersonDBOpenHelper(this); helper.getWritableDatabase();*/ PersonDao dao = new PersonDao(this); Cursor cursor = dao.findAllCursor();//查询所有的记录并返回Cursor while(cursor.moveToNext()){ int id = cursor.getInt(cursor.getColumnIndex("_id")); String name = cursor.getString(cursor.getColumnIndex("name")); String phone = cursor.getString(cursor.getColumnIndex("phone")); int money = cursor.getInt(cursor.getColumnIndex("money")); Log.i(TAG,id+" name: "+name+" phone: "+phone+" money: "+money); } //(Context context, int layout, Cursor c, String[] from, int[] to) if (Build.VERSION.SDK_INT >= 11) { // api 11以上才可以运行 listView.setAdapter(new SimpleCursorAdapter( this, R.layout.list_item, cursor, new String[] { "name", "phone", "money" }, new int[] {R.id.name_textView, R.id.phone_textView, R.id.money_textView }, 0)); Log.i(TAG,"我是高版本api"); } else { // api 11 以下运行 listView.setAdapter(new SimpleCursorAdapter(this, R.layout.list_item, cursor, new String[] { "name", "phone", "money" }, new int[] {R.id.name_textView, R.id.phone_textView, R.id.money_textView })); Log.i(TAG,"我是低版本api"); } } }
自定义Adapter:继承BaseAdapter
整体布局文件:Main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent" tools:context=".MainActivity" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:text="ID" android:layout_weight="1" android:textSize="18sp" android:gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:text="姓名" android:layout_weight="1" android:textSize="18sp" android:gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:text="电话" android:layout_weight="1" android:textSize="18sp" android:gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:text="收入" android:textSize="18sp" android:layout_weight="1" android:gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <ListView android:id="@+id/lv" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
Item布局文件
<?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" > <TextView android:id="@+id/id_TextView" android:text="ID" android:gravity="center_horizontal" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" android:textSize="16sp" /> <TextView android:id="@+id/name_TextView" android:text="姓名" android:layout_weight="1" android:gravity="center_horizontal" android:layout_width="0dip" android:layout_height="match_parent" android:textSize="16sp" /> <TextView android:id="@+id/phone_TextView" android:text="电话" android:layout_weight="1" android:gravity="center_horizontal" android:layout_width="0dip" android:layout_height="match_parent" android:textSize="16sp" /> <TextView android:id="@+id/amount_TextView" android:text="收入" android:layout_weight="1" android:gravity="center_horizontal" android:layout_width="0dip" android:layout_height="match_parent" android:textSize="16sp" /> </LinearLayout>
MainActivity
public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private List<Person> persons ; private PersonDao dao; private ListView lv ; ListAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv = (ListView) findViewById(R.id.lv); dao = new PersonDao(this); persons = dao.findAll(); adapter = new ListAdapter(); Log.i(TAG,adapter.getCount()+""); lv.setAdapter(adapter);//为ListView 设置适配器,适配器中已经将数据填充到了布局中 //为ListView设置点击事件 lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Person person = persons.get(position); String name = person.getName(); int personid = person.getId(); //Toast.makeText(MainActivity.this, personid, 1).show(); Toast.makeText(MainActivity.this, "id:"+personid, 1).show(); } }); //为ListView设置长按监听:删除一条数据 lv.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { Person person = persons.get(position); int personid = person.getId(); dao.delete(personid);//从数据库中将数据删除 persons.remove(position);//从适配器中删除 adapter.notifyDataSetChanged();//通知数据适配器 更新界面 return true;//false 当前的事件 不会被消费掉,继续执行,OnItemClickListener会Toaster //true 当前事件执行到这里 就终止了,后面的不再执行, //比如setOnItemClickListener的Toaster就不执行 }}); }
private final class ListAdapter extends BaseAdapter{ @Override public int getCount() { return persons.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } //返回当前位置对应的view对象,显示内容 @Override public View getView(int position, View convertView, ViewGroup parent) { //position代表位置 //通过View关联自定义Item布局,进行填充 View view = View.inflate(MainActivity.this, R.layout.list_item, null); //获取指定位置的对象 Person person = persons.get(position); //获取要显示的组件,注意findViewById的调用对象是上面填充了Item的布局的对象View TextView id_TextView = (TextView)view.findViewById(R.id.id_TextView); TextView name_TextView = (TextView)view.findViewById(R.id.name_TextView); TextView amount_TextView =(TextView)view.findViewById(R.id.amount_TextView); TextView phone_TextView =(TextView)view.findViewById(R.id.phone_TextView); id_TextView.setText(person.getId()+""); name_TextView.setText(person.getName()); amount_TextView.setText(person.getAmount()+""); phone_TextView.setText(person.getPhone()); return view; } } }
工具类:查询所有的记录,这里省略了数据库
public List<Person> findAll(){ List<Person> persons = new ArrayList<Person>(); SQLiteDatabase db = helper.getReadableDatabase(); //query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) Cursor cursor = db.query("person", new String[]{"id","name","phone","amount"}, null, null, null, null, null, null); while(cursor.moveToNext()){ int id = cursor.getInt(cursor.getColumnIndex("id")); String name = cursor.getString(cursor.getColumnIndex("name")); String phone = cursor.getString(cursor.getColumnIndex("phone")); String amount = cursor.getString(cursor.getColumnIndex("amount")); persons.add(new Person(id,name,phone,Float.valueOf(amount))); } cursor.close();//关闭游标 db.close();//关闭数据库 return persons; }