ListView作为一个列表展示的容器,里面可以包含多个数据项,数据项可以是简单的只有一个TextView的布局,也可以是复杂的组合布局。

继承关系如下:

类 ListView

java.lang.Object
  继承者 android.view.View
      继承者 android.view.ViewGroup
          继承者 android.widget.AdapterView<ListAdapter>
              继承者 android.widget.AbsListView
                  继承者 android.widget.ListView
在API文档中还有一句描述:

A view that shows items in a vertically scrolling list. The items come from the ListAdapter associated with this view. 

ListView是一种列表可以在垂直方向滚动的视图,数据项来自于和这个视图绑定的ListAdapter。那么有一种特殊的情况下ListView或许不可用,那就是在ScrollView下。笔者无意间发现的,笔者为了偷懒把关于Widgets所有的实验都放到了一个项目中在顶层用了一个ScrollView,在这种情况下添加ListView只能显示第一条数据。

一、最简单的ListView

使用方法类似于Spinner,需要一个数据源最简单的是数组,一个Adapter,然后将ListView和这个Adapter通过ListView的setAdapter()方法绑定,这样一个最简单的ListView就成功了。

                ListView lv_01 = (ListView)findViewById(R.id.lv_listview01);
		String []itmes = new String[]{"逍遥","灵儿","月如"};
		ArrayAdapter <String>aadapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1
				,itmes);
		lv_01.setAdapter(aadapter);
运行结果:

二、自定义的ListView

先看一下API中ListView的setAdapter()的方法解释:

public void setAdapter(ListAdapter adapter)
Sets the data behind this ListView. The adapter passed to this method may be wrapped by a WrapperListAdapter, depending on the ListView features currently in use. For instance, adding headers and/or footers will cause the adapter to be wrapped. 
这个方法为ListView设置数据,这个适配器通过这个方法传递数据,这个数据可能会被一个组装适配器组装,样式取决于当前使用的ListView特点,比如添加页面或者页脚。


通过这个解释我们可以发现ListView的样式是通过Adapter设置的,下面继续看adapter的定义:

Extended Adapter that is the bridge between a ListView and the data that backs the list. Frequently that data comes from a Cursor, but that is not required. The ListView can display any data provided that it is wrapped in a ListAdapter.

扩展的adapter是数据和视图的桥梁,通常数据来自一个游标但是通常不需要,listview可以呈现任何提供给它的数据,这数据是通过listAdapter组装的。

到这里我们了解到:数据源 + Adapter + 布局 就可以了得到一个我们自定义的ListView了。

数据源:数组 或者 List<Map>

Adapter:SimpleAdapter 拓展性比较好,可以放各种其他控件进行组合。

布局:layout.xml

关于SimpleAdapter的参数相信很多初学者和笔者一样搞的是一塌糊涂,因为参数太多了,而且还很难记忆,先来看一下官方API中的解释:

SimpleAdapter

public SimpleAdapter(Context context,
                     List<? extends Map<String,?>> data,
                     int resource,
                     String[] from,
                     int[] to)
参数:
context - The context where the View associated with this SimpleAdapter is running
data - A List of Maps. Each entry in the List corresponds to one row in the list. The Maps contain the data for each row, and should include all the entries specified in "from"
resource - Resource identifier of a view layout that defines the views for this list item. The layout file should include at least those named views defined in "to"
from - A list of column names that will be added to the Map associated with each item.
to - The views that should display column in the "from" parameter. These should all be TextViews. The first N views in this list are given the values of the first N columns in the from parameter1.context好理解,当前上下文。

2.data,首先它是一个装有某种Map的List集合(一个List里面的内容必须是某种Map),后面的有点绕,这个List中的每一项(应该是下面from这个参数的)要和List的一行相同(无语),这个Map中每一行包含的数据,应该包含"from"中的每一项。光看文字估计会看的疯掉,还是看一下例子代码就清楚了:

SimpleAdapter sa = new SimpleAdapter(this, getData(), R.layout.item_listview, 
				new String[]{"icon","content","content1"}, new int[]{R.id.iv_icon,R.id.tv_content,R.id.tv_content1});

private List<Map<String,Object>> getData(){
		List<Map<String,Object>> myList = new ArrayList<Map<String,Object>>();
		Map<String,Object> map = new HashMap<String, Object>();
		
		map.put("icon",R.drawable.ic_launcher);
		map.put("content", "xiaoyao");
		map.put("content1", "男主角");
		myList.add(map);
		map = new HashMap<String, Object>();
		map.put("icon",R.drawable.ic_launcher);
		map.put("content", "linger");
		map.put("content1", "女主角");
		myList.add(map);
		map = new HashMap<String, Object>();
		map.put("icon",R.drawable.ic_launcher);
		map.put("content", "月如");
		map.put("content1", "女主角");
		myList.add(map);
		map = new HashMap<String, Object>();
		map.put("icon",R.drawable.ic_launcher);
		map.put("content", "tangyu");
		map.put("content1", "男主角");
		myList.add(map);
		
		return myList;
	}

对比发现:应该说的是from中的参数应该是map的key。笔者是这样理解的,如果不对的话,欢迎指出。

3.这个参数定义了一个layout来描述这个view中每一项的样式,并且这个layout至少应该包含to中的参数所定义的views(指的是ID)

4.这个视图应该展现出在from的参数中的列所对应的值,他们必须都是TextView而且显示顺序是根据to中列的顺序来定的。

大体的意思是参数3中(描述每一个item样式的layout)出现的id至少要包括4中所列出来的,并且在实际的呈现顺序就是按照这个列的顺序。

比较完整的代码如下:MainActivity,由于继承了ListActivity,便不用在xml中定义ListView了。

<pre name="code" class="java">public class MainActivity extends ListActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		SimpleAdapter sa = new SimpleAdapter(this, getData(), R.layout.item_listview, 
				new String[]{"icon","content","content1"}, new int[]{R.id.iv_icon,R.id.tv_content,R.id.tv_content1});	
		this.setListAdapter(sa);
		
		
	}	
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		// TODO Auto-generated method stub
		Log.i("abc",getData().get(position).toString());
	}
	@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;
	}

	private List<Map<String,Object>> getData(){
		List<Map<String,Object>> myList = new ArrayList<Map<String,Object>>();
		Map<String,Object> map = new HashMap<String, Object>();
		
		map.put("icon",R.drawable.ic_launcher);
		map.put("content", "xiaoyao");
		map.put("content1", "男主角");
		myList.add(map);
		map = new HashMap<String, Object>();
		map.put("icon",R.drawable.ic_launcher);
		map.put("content", "linger");
		map.put("content1", "女主角");
		myList.add(map);
		map = new HashMap<String, Object>();
		map.put("icon",R.drawable.ic_launcher);
		map.put("content", "月如");
		map.put("content1", "女主角");
		myList.add(map);
		map = new HashMap<String, Object>();
		map.put("icon",R.drawable.ic_launcher);
		map.put("content", "tangyu");
		map.put("content1", "男主角");
		myList.add(map);
		
		return myList;
	}
}


 item_listview.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" >
    
    <ImageView 
        android:id="@+id/iv_icon"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        />
    
    <TextView 
        android:id="@+id/tv_content"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        />
   
    <TextView 
        android:id="@+id/tv_content1"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        />
    
</LinearLayout>

运行结果:



由于这里直接继承了ListActivity因此可以直接通过重写onListItemClick()这个回调方法来直接获取点击事件的值。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐