三种实现方法,由浅入深。这中间要注意Adapter的用法,其实你要是看过Android的文档,你会发现有很多Adapter,
如果你还不太清楚适配器模式,可以先补补这方面的知识。在实际工作中,设计模式是个很好的帮手。
两个layout文件:
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent" ></ListView> </LinearLayout>
listview.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linerlayout1" android:orientation="vertical" android:layout_height="fill_parent" android:layout_width="fill_parent" > <TextView android:id="@+id/person_name" android:textSize="23sp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/person_age" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/person_email" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/person_address" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
package com.linc.listview; import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.ListView; public class LincListViewActivity extends Activity { private final static String[] data = {"张飞","张辽","张角","张三丰","张牙舞爪","张灯结彩","张唑啉","张大民"}; //创建数据源. Zhang[] data2 = new Zhang[]{ new Zhang("张飞",38,"zhangfei@gmail.com","燕山"), new Zhang("张辽",36,"zhangliao@sina.com","雁门"), new Zhang("张角",51,"zhangjiao@gmail.com","钜鹿"), new Zhang("张三丰",200,"sanfeng@gmail.com","辽东"), new Zhang("张牙舞爪",25,"5zhao@gmail.com","冀州"), new Zhang("张灯结彩",25,"5zhao@gmail.com","冀州") , new Zhang("张唑啉",25,"5zhao@gmail.com","冀州") , new Zhang("张大民",25,"5zhao@gmail.com","冀州") , new Zhang("张牙舞爪",25,"5zhao@gmail.com","冀州") }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ListView listview = (ListView)findViewById(R.id.listview); /* * 第一种:普通字符串 */ ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,data); /* * 第二种:文艺类对象 */ ArrayAdapter<Zhang> adapter2 = new ArrayAdapter<Zhang>(this, android.R.layout.simple_list_item_1,data2); /* * 第三种:自定义适配器 */ ListAdapter adapter3 = new ListAdapter(this, R.layout.listview,data2) ;//okay, the resource id is passed. listview.setAdapter(adapter3); } }
package com.linc.listview; public class Zhang { private String name; private int age; private String email; private String address; public String getName() { return name; } public int getAge() { return age; } public String getEmail() { return email; } public String getAddress() { return address; } public Zhang(String name, int age, String email, String address) { super(); this.name = name; this.age = age; this.email = email; this.address = address; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", email=" + email + ", address=" + address + "]"; } }
package com.linc.listview; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; public class ListAdapter extends ArrayAdapter<Zhang> { private LayoutInflater mInflater; public ListAdapter(Context context, int textViewResourceId,Zhang[] obj) { super(context, textViewResourceId,obj); // TODO Auto-generated constructor stub this.mInflater = LayoutInflater.from(context); } @Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView == null){ //创建新的view视图. convertView = mInflater.inflate(R.layout.listview, null); //see above, you can use the passed resource id. } ViewHolder holder = null; if(holder==null){ holder = new ViewHolder(); //查找每个ViewItem中,各个子View,放进holder中 holder.name = (TextView) convertView.findViewById(R.id.person_name); holder.age = (TextView) convertView.findViewById(R.id.person_age); holder.email = (TextView) convertView.findViewById(R.id.person_email); holder.address = (TextView) convertView.findViewById(R.id.person_address); //保存对每个显示的ViewItem中, 各个子View的引用对象 convertView.setTag(holder); } else// I think this a bug, program can not run here!!!--linc2014.11.12 { holder = (ViewHolder)convertView.getTag(); } //获取当前要显示的数据 Zhang person = getItem(position); holder.name.setText(person.getName()); holder.age.setText(String.valueOf(person.getAge())); holder.email.setText(person.getEmail()); holder.address.setText(person.getAddress()); return convertView; } private static class ViewHolder { TextView name; TextView age; TextView email; TextView address; } }
还可以参考:View Tag的介绍
或者对比着GridView来学习一下它们的异同,Android自定义GridView之实现一个图片加多个文本框
它们的Adapter一个是继承自ArrayAdapter,另一个是BaseAdapter。
另外,API demo中相关的例子一定要看看。那才是真正的宝藏呢。
下面直接给出List14源码:
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.apis.view; import android.app.ListActivity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import android.widget.ImageView; import android.graphics.BitmapFactory; import android.graphics.Bitmap; import com.example.android.apis.R; /** * Demonstrates how to write an efficient list adapter. The adapter used in this example binds * to an ImageView and to a TextView for each row in the list. * * To work efficiently the adapter implemented here uses two techniques: * - It reuses the convertView passed to getView() to avoid inflating View when it is not necessary * - It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary * * The ViewHolder pattern consists in storing a data structure in the tag of the view returned by * getView(). This data structures contains references to the views we want to bind data to, thus * avoiding calls to findViewById() every time getView() is invoked. */ public class List14 extends ListActivity { private static class EfficientAdapter extends BaseAdapter { private LayoutInflater mInflater; private Bitmap mIcon1; private Bitmap mIcon2; public EfficientAdapter(Context context) { // Cache the LayoutInflate to avoid asking for a new one each time. mInflater = LayoutInflater.from(context); // Icons bound to the rows. mIcon1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon48x48_1); mIcon2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon48x48_2); } /** * The number of items in the list is determined by the number of speeches * in our array. * * @see android.widget.ListAdapter#getCount() */ public int getCount() { return DATA.length; } /** * Since the data comes from an array, just returning the index is * sufficent to get at the data. If we were using a more complex data * structure, we would return whatever object represents one row in the * list. * * @see android.widget.ListAdapter#getItem(int) */ public Object getItem(int position) { return position; } /** * Use the array index as a unique id. * * @see android.widget.ListAdapter#getItemId(int) */ public long getItemId(int position) { return position; } /** * Make a view to hold each row. * * @see android.widget.ListAdapter#getView(int, android.view.View, * android.view.ViewGroup) */ public View getView(int position, View convertView, ViewGroup parent) { // A ViewHolder keeps references to children views to avoid unneccessary calls // to findViewById() on each row. ViewHolder holder; // When convertView is not null, we can reuse it directly, there is no need // to reinflate it. We only inflate a new View when the convertView supplied // by ListView is null. if (convertView == null) { convertView = mInflater.inflate(R.layout.list_item_icon_text, null); // Creates a ViewHolder and store references to the two children views // we want to bind data to. holder = new ViewHolder(); holder.text = (TextView) convertView.findViewById(R.id.text); holder.icon = (ImageView) convertView.findViewById(R.id.icon); convertView.setTag(holder); } else { // Get the ViewHolder back to get fast access to the TextView // and the ImageView. holder = (ViewHolder) convertView.getTag(); } // Bind the data efficiently with the holder. holder.text.setText(DATA[position]); holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2); return convertView; } static class ViewHolder { TextView text; ImageView icon; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setListAdapter(new EfficientAdapter(this)); } private static final String[] DATA = Cheeses.sCheeseStrings; }