在Android讲义中的示例中:
一:简单的string列表:
1,创建 String类型的ListView,通过 string [] 填充数据,或者通过string.xml创建数据;
2,在 plistview.setOnItemClickListener(newAdapterView.OnItemClickListener() 响应函数中,通过类的成员变量获取;
这里我简单修改一下:
ListView 是和 ArrayAdapter 配合使用的,ArrayAdapter就表示链表,ListView是容器和消息响应;
ArrayAdapter 本身就可以添加删除item:
示例:
创建:
ListView plistview = (ListView) findViewById(R.id.listView); //item默认情况是TextView,可以直接用系统默认自带的xml文件,如:android.R.layout.simple_list_item_1;也可以参考系统的写自己的itme的xml;ArrayAdapter<String> pArayAdapter = new ArrayAdapter<String>(this, R.layout.listview_item); plistview.setAdapter(pArayAdapter); for (int i = 0; i < 100; i++) { pArayAdapter.add("string listview item " + i); }消息响应:
//通过onItemClick中的参数获取控制相关链表中的item,因为类型是创建时候定义的,所以onItemClick中的item要类型强制转换;plistview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { String strItem = (String) parent.getItemAtPosition(position); //强制类型转换 + item获取; TextView pTview = (TextView)findViewById(R.id.idc_TextVIew); pTview.setText( strItem ); } });
关于: R.layout.listview_item ;
这里的item就是一个TextView;在XML文件中定义的TextView;
但是要注意,这个TextView的定义不可以在Layout中定义,而是在一个单独的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:weightSum="1"> <TextView android:layout_width="wrap_content" android:layout_height="100dp" android:textAppearance="?android:attr/textAppearanceLarge" android:text="Large Text" android:id="@+id/textView3" android:layout_weight="0.38"/></LinearLayout>
而是:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="107dp" android:textAppearance="?android:attr/textAppearanceLarge" android:text="Large Text" android:id="@+id/textView2" android:layout_weight="0.81"/>
在AndroidStudio中添加的话,可以直接右键添加Layout,然后在XML的Design中添加一个TextView,然后通过属性设置相关参数;
设置好后,在XML的Text中删除Layout,在相关的TextView中添加xmlns:android;
public ArrayAdapter (Context context, int resource)
Added in API level 1Constructor
Parameters
context The current context. resource The resource ID for a layout file containing a TextView to use when instantiating views.
更加具体的方法可以参考帮助文档;
二:可扩展的ListView:
通常一个ListView简单显示字符串,就直接用ArrayAdapter 就可以了;
如果想在列表中显示复杂的界面,如果每一个列表项item都是一个View或多个View,那么就需要自己重写BaseAdapter了;
ArrayAdapter就是实现了BaseAdapter可以参考:
关于BaseAdapter简单应用可以参考《Android讲义》这本书;
这里主要说一下BaseAdapter的应用;
在Android studio中可以在MainActivity类中直接通过匿名类的方法实现继承BaseAdapter类,这样可以方便的应用Context参数,就是直接用主窗口的this就可以了;
但是一般为了更好的模块化,可以右键直接创建java class,然后 extendsBaseAdapter就可以了;但是如果要用Context,可以同构造函数直接传参数,或是添加一个set函数添加;
然后通过快捷键,“Alt + Insert”,实现Implement需要实现的函数;
重要的函数有
public int getCount() :返回值表示了显示的列表数; 通过函数参数修改返回值,然后重新ListView.setAdapter重新加载显示列表控件;
public View getView(int position, View convertView, ViewGroup parent) :列表中显示View的;
因为Android中的所有控件都是View包括Layout,所以可以返回非常复杂的列表Item;
position参数,表示当前加载的Viewd的索引序号值;
public class TestBaseAdpter extends BaseAdapter { public TestBaseAdpter( Context pContext ) { m_pContext = pContext; } Context m_pContext; /** * How many items are in the data set represented by this Adapter. * * @return Count of items. */ @Override public int getCount() { return 1000; } /** * Get the data item associated with the specified position in the data set. * * @param position Position of the item whose data we want within the adapter's * data set. * @return The data at the specified position. */ @Override public Object getItem(int position) { return null; } /** * Get the row id associated with the specified position in the list. * * @param position The position of the item within the adapter's data set whose row id we want. * @return The id of the item at the specified position. */ @Override public long getItemId(int position) { return 0; } /** * Get a View that displays the data at the specified position in the data set. You can either * create a View manually or inflate it from an XML layout file. When the View is inflated, the * parent View (GridView, ListView...) will apply default layout parameters unless you use * {@link LayoutInflater#inflate(int, ViewGroup, boolean)} * to specify a root view and to prevent attachment to the root. * * @param position The position of the item within the adapter's data set of the item whose view * we want. * @param convertView The old view to reuse, if possible. Note: You should check that this view * is non-null and of an appropriate type before using. If it is not possible to convert * this view to display the correct data, this method can create a new view. * Heterogeneous lists can specify their number of view types, so that this View is * always of the right type (see {@link #getViewTypeCount()} and * {@link #getItemViewType(int)}). * @param parent The parent that this view will eventually be attached to * @return A View corresponding to the data at the specified position. */ @Override public View getView(int position, View convertView, ViewGroup parent) { TextView pView = new TextView( m_pContext ); pView.setText( "新建字符串" ); return pView; } }
如果要查看复杂的设计方法, 一般可以添加 List链表,返回的是List.count(), 这样就可以比较容易动态控制链表,具体可以参考Android中的ArrayAdapter;
三:用简单的方式实现ListView的扩展:
从上述实现BaseAdapter来看,有些麻烦,所以想一个简单的方法实现ListView的扩展;
还是从ArrayAdapter入手;先看帮助文档:
从帮助文档可以看出, ArrayAdapter就是继承实现了BaseAdapter,而且,ArrayAdapter是泛型的,支持任何类型,
所以:理论上可以经任何View,任何类绑定到ArrayAdapter中;
但是:ArrayAdapter本身的实现又有一些限制,ArrayAdapter构造函数接受的样式文件里只含有一个textview,然后它把接受到的数据toString后(即调用数据对象的toString方法,如果是string类型,就直接显示了;)展示在textview里。
就是说,对于ArrayAdapter来说,不论传输什么类型的class类,最后都会显示为toString后的字符串;将字符串显示到View上;
所以:我们可以 继承 ArrayAdapter,然后修改getView函数;
我们可以参考ArrayAdapter的getView函数的实现,然后返回任何我们希望的View;
示例:
参考ArrayAdapter传入的源码,我们知道我们add的任何T类型都会被添加到里面的链表中,所以为了快速实现我们的想法,我们可以直接getView中返回链表中添加的T类型(如果是View的话,当然一般我们要显示的必然是View,所以添加的时候可以直接添加View获其子类);
//自定义类实现:
class MyArrayAdapter extends ArrayAdapter<View> { public MyArrayAdapter(Context context, int resource) { super(context, resource); } public MyArrayAdapter(Context context, int resource, int textViewResourceId) { super(context, resource, textViewResourceId); } public MyArrayAdapter(Context context, int resource, View[] objects) { super(context, resource, objects); } public MyArrayAdapter(Context context, int resource, int textViewResourceId, View[] objects) { super(context, resource, textViewResourceId, objects); } public MyArrayAdapter(Context context, int resource, List<View> objects) { super(context, resource, objects); } public MyArrayAdapter(Context context, int resource, int textViewResourceId, List<View> objects) { super(context, resource, textViewResourceId, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { return getItem( position ); // return super.getView(position, convertView, parent); } }
//类应用:
MyArrayAdapterm_MyArrayAdapterButton=null;
protected void onCreate(Bundle savedInstanceState)
{...
m_MyArrayAdapterButton = new MyArrayAdapter(this, android.R.layout.simple_list_item_1 );
}
public void onClick(View v) {
Button pbtn = new Button( this );
pbtn.setText("btn: " + m_nCount++); m_MyArrayAdapterButton.add( pbtn ); listView.setAdapter( m_MyArrayAdapterButton ); }
上述示例实质返回了按钮,如果需要可以返回任何复杂的界面,当然要可以返回Layout创建的界面;
最后转两篇文章:
说明:这两篇文章应该是一个人写的,这个示例有一定的说明作用,但是这样的封装自定义类,不能很好地控制每一个item,而且会造成不确定性;
建议读者在写代码的时候尽量考虑接口的简单,类的封装,和封装的易用性,高内聚,低耦合;
http://blog.csdn.net/nairuohe/article/details/6457300
http://www.cnblogs.com/wenjiang/p/3196205.html