您的位置:首页 > 产品设计 > UI/UE

第二章 吸引你的眼球—UI编程(5)

2014-12-31 09:33 218 查看

2.1.7列表组件(ListView)

ListView在Android中也是一个使用比较频繁的组件。它相对于其他的基本组件来说,使用起来稍微复杂一些,需要注意的也比较多,尤其是和其他一些组件组合起来使用的情况。在Android中,ListView用来显示一个列表的组件,它以列表的形式展示具体的内容,并且能够根据数据的长度自适应显示。用户可以选择并操作这个列表,同时会触发相应的事件:当鼠标滚动时会触发setOnItemSelectedListener事件;当点击列表时会触发setOnItemClickListener事件。列表的显示需要三个元素:1)ListView:用来展示列表的View;2)适配器:用来把数据映射到ListView上的中介;3)数据:具体的将被映射的字符串、图片或者其他基本组件。根据列表的适配器类型,列表分为三种:ArrayAdapter、SimpleAdapter和SimpleCursorAdapter。其中以ArrayAdapter最为简单,只能展示一行字;SimpleAdapter有最好的扩充性,可以自定义出各种效果;SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方便地把数据库中的内容以列表的形式展示出来。下面,我们分别以一个例子来看看这些ListView是如何实现的。1)首先,我们来看看ArrayAdapter,部分代码如下:
privateListViewlistView;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);listView=newListView(this);listView.setAdapter(newArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,getData()));setContentView(listView);}privateList<String>getData(){List<String>data=newArrayList<String>();data.add("第一行");data.add("第二行");data.add("第三行");returndata;}
让我们来看看效果,如图2-15所示:

图2-15ArrayAdapter的使用这种列表使用了ArrayAdapter(Contextcontext,inttextViewResourceId,List<T>objects)来装配数据,ArrayAdapter的构造需要三个参数,依次为Context、布局文件(注意这里的布局文件描述的是列表的每一行的布局,android.R.layout.simple_list_item_1是系统定义好的布局文件只显示一行文字,数据源(一个List集合)。同时用setAdapter()完成适配。2)SimpleCursorAdapter是把从游标得到的数据进行列表显示,并可以把指定的列映射到对应的TextView中。下面的例子从电话簿中把联系人显示到类表中。先在通讯录中添加一个联系人作为数据库的数据。然后获得一个指向数据库的Cursor并且定义一个布局文件(当然也可以使用系统自带的)。
privateListViewlistView;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);listView=newListView(this);Cursorcursor=getContentResolver().query(People.CONTENT_URI,null,null,null,null);startManagingCursor(cursor);ListAdapterlistAdapter=newSimpleCursorAdapter(this,android.R.layout.simple_expandable_list_item_1,cursor,newString[]{People.NAME},newint[]{android.R.id.name});listView.setAdapter(listAdapter);setContentView(listView);}
SimpleCursorAdapter构造函数前面3个参数和ArrayAdapter是一样的,最后两个参数:一个包含数据库的列的String型数组,一个包含布局文件中对应组件id的int型数组。其作用是自动的将String型数组所表示的每一列数据映射到布局文件对应id的组件上。上面的代码,将NAME列的数据一次映射到布局文件的id为name的组件上。另外,读取通讯录需要在AndroidManifest.xml中如权限:<uses-permissionandroid:name="android.permission.READ_CONTACTS"></uses-permission>。效果如图2-16所示:

图2-16SimpleCursorAdapter的使用3)SimpleAdapter是我们比较常用的一种列表。它的扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等。我们也以一个例子来看看它是如何实现的。首先,我们定义一个list_item.xml文件来定义list的内容:
<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/name_textview"android:layout_height="wrap_content"android:layout_width="100dp"/><TextViewandroid:id="@+id/phone_textview"android:layout_height="wrap_content"android:layout_width="150dp"/><Buttonandroid:id="@+id/call_button"android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="呼叫"/></LinearLayout>
在这里,我们定义两个TextView、一个Button按钮,接着我们新建一个MyList类继承自ListActivity(ListActivity类继承Activity类,默认绑定了一个ListView(列表视图)界面组件,并提供一些与列表视图、处理相关的操作),部分代码如下:
@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);SimpleAdapteradapter=newSimpleAdapter(this,getData(),R.layout.list_item,newString[]{"name","phone"},newint[]{R.id.name_textview,R.id.phone_textview});setListAdapter(adapter);}privateList<Map<String,Object>>getData(){List<Map<String,Object>>list=newArrayList<Map<String,Object>>();Map<String,Object>map=newHashMap<String,Object>();map.put("name","张三");map.put("phone","13472345623");list.add(map);map=newHashMap<String,Object>();map.put("name","李四");map.put("phone","13472345623");list.add(map);map=newHashMap<String,Object>();map.put("name","王五");map.put("phone","13472345623");list.add(map);returnlist;
}
下面,我们来看看效果,如图2-17所示:


图2-17SimpleAdapter的使用
--------------------------------------------试着放个广告现在没工作要生存没办法平安陆金所隶属于平安集团的p2p平台年投资回报率7%-9%是替代银行理财的首选个人经验教训推荐投资安鑫或者有担保的彩虹项目不要投资安e那个几乎无法转让想提前提现非常困难注册链接http://affiliate.lufax.com/action/36XBU用此链接注册你我都会有几十元的额外现金奖励--------------------------------------------
当我们点击按钮时,需要进行一系列的操作,但是上面那样做无法满足我们的需求。这是因为按钮是无法映射的,即使我们成功的用布局文件显示出了按钮也无法添加按钮的响应,这样的话就需要我们做一些别的事情来监听按钮事件:
首先,需要定义一个类ViewHolder,它里面定义列表中的三个组件:
publicfinalclassViewHolder{publicTextViewname;publicTextViewphone;publicButtoncall;}
然后,我们定义一个mData用于存储数据:
[code]private
List<Map<String,Object>>mData;
接着,我们定义一个类MyAdapter继承自BaseAdapter:
publicclassMyAdapterextendsBaseAdapter{privateLayoutInflatermInflater;publicMyAdapter(Contextcontext){this.mInflater=LayoutInflater.from(context);}@OverridepublicintgetCount(){returnmData.size();}@OverridepublicObjectgetItem(intarg0){returnnull;}@OverridepubliclonggetItemId(intarg0){return0;}@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupparent){ViewHolderholder=null;if(convertView==null){holder=newViewHolder();convertView=mInflater.inflate(R.layout.list_item,null);holder.name=(TextView)convertView.findViewById(R.id.name_textview);holder.phone=(TextView)convertView.findViewById(R.id.phone_textview);holder.call=(Button)convertView.findViewById(R.id.call_button);convertView.setTag(holder);}else{holder=(ViewHolder)convertView.getTag();}holder.name.setText((String)mData.get(position).get("name"));holder.phone.setText((String)mData.get(position).get("phone"));holder.call.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){Log.d(“test”,“callthenumber”);}});returnconvertView;}}
最后是onCreate方法:
@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);mData=getData();MyAdapteradapter=newMyAdapter(this);setListAdapter(adapter);}
这样的话,我们就可以对列表中的每一个组件进行事件监听了。如果我们要对ListView的每一行的点击事件进行监听的话,我们需要实现OnItemClickListener接口中的onItemClick方法:
@OverridepublicvoidonItemClick(AdapterView<?>arg0,Viewarg1,intarg2,longarg3){Log.d("test","item:"+arg2);
}
上面介绍的是使用ListActivity方式,因为它默认绑定了一个ListView,所以我们并不需要自己定义ListView就能直接使用了,但是很多时候,我们可能是在布局中自己定义一个ListView,这样我们可以自己来控制它的大小等属性,例如:
<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><ListViewandroid:id="@android:id/list"android:layout_width="fill_parent"android:layout_height="fill_parent"/>
</LinearLayout>
这里需要注意的是,这个ListView的id必须为"@android:id/list",然后我们通过以下的代码来实现:
AdapterView<?>mAdapterView=(ListView)findViewById(android.R.id.list);((AbsListView)mAdapterView).setAdapter(adapter);
如果用这种方法的话,我们除了可以实现OnItemClickListener接口之外,也可以直接对ListView绑定监听事件来达到处理点击列表每一行的效果:
mAdapterView.setOnItemClickListener(newOnItemClickListener(){@OverridepublicvoidonItemClick(AdapterView<?>arg0,Viewarg1,intarg2,longarg3){Log.d("test","item:"+arg2);}
});
经验分享:
有的时候,我们为列表添加了OnItemClickListener监听,但是点击每一行后并没有效果。这是因为,如果列表中有CheckBox或者是Button等存在的话,他们默认是获得焦点的,而ListView的item能被选中的条件是要获得焦点,因为我们在根控件下设置如下属性:
android:descendantFocusability="blocksDescendants",这样ItemLayout就屏蔽了所有子控件获取Focus的权限,而自己能够获得焦点响应点击事件了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: