android 实现QQ好友列表(扩展listview:ExpandableListView)
16lz
2021-12-26
在某些android开发群里,看到有些新手问怎么实现QQ好友列表,其实网上一搜挺多的。接触Android,也才一年的时间,大部分时间花在工作上(解bug。。。),界面上开发很少参与。自己维护的系统应用里,有个ExpandableListView的界面(其实android例子APIDemo也有类似的例子)就在这里写个Demo供新手参考。
ExpandableListView的用法:难点就是重写BaseExpandableListAdapter及提供的数据源。
下面看看继承BaseExpandableListAdapter的适配器:
[java] view plain copy
- <spanxmlns="http://www.w3.org/1999/xhtml">packagecom.xyz.expande;
- importjava.util.List;
- importandroid.app.AlertDialog;
- importandroid.content.Context;
- importandroid.graphics.Bitmap;
- importandroid.graphics.Bitmap.Config;
- importandroid.graphics.Canvas;
- importandroid.graphics.Paint;
- importandroid.graphics.PixelFormat;
- importandroid.graphics.PorterDuff.Mode;
- importandroid.graphics.PorterDuffXfermode;
- importandroid.graphics.Rect;
- importandroid.graphics.RectF;
- importandroid.graphics.drawable.BitmapDrawable;
- importandroid.graphics.drawable.Drawable;
- importandroid.util.Log;
- importandroid.view.LayoutInflater;
- importandroid.view.View;
- importandroid.view.ViewGroup;
- importandroid.widget.BaseExpandableListAdapter;
- importandroid.widget.ImageView;
- importandroid.widget.TextView;
- publicclassExpandeAdapterextendsBaseExpandableListAdapter{
- privateContextmContext;
- privateLayoutInflatermInflater=null;
- privateString[]mGroupStrings=null;
- privateList<List<Item>>mData=null;
- publicExpandeAdapter(Contextctx,List<List<Item>>list){
- mContext=ctx;
- mInflater=(LayoutInflater)mContext
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mGroupStrings=mContext.getResources().getStringArray(R.array.groups);
- mData=list;
- }
- publicvoidsetData(List<List<Item>>list){
- mData=list;
- }
- @Override
- publicintgetGroupCount(){
- //TODOAuto-generatedmethodstub
- returnmData.size();
- }
- @Override
- publicintgetChildrenCount(intgroupPosition){
- //TODOAuto-generatedmethodstub
- returnmData.get(groupPosition).size();
- }
- @Override
- publicList<Item>getGroup(intgroupPosition){
- //TODOAuto-generatedmethodstub
- returnmData.get(groupPosition);
- }
- @Override
- publicItemgetChild(intgroupPosition,intchildPosition){
- //TODOAuto-generatedmethodstub
- returnmData.get(groupPosition).get(childPosition);
- }
- @Override
- publiclonggetGroupId(intgroupPosition){
- //TODOAuto-generatedmethodstub
- returngroupPosition;
- }
- @Override
- publiclonggetChildId(intgroupPosition,intchildPosition){
- //TODOAuto-generatedmethodstub
- returnchildPosition;
- }
- @Override
- publicbooleanhasStableIds(){
- //TODOAuto-generatedmethodstub
- returnfalse;
- }
- @Override
- publicViewgetGroupView(intgroupPosition,booleanisExpanded,
- ViewconvertView,ViewGroupparent){
- //TODOAuto-generatedmethodstub
- if(convertView==null){
- convertView=mInflater.inflate(R.layout.group_item_layout,null);
- }
- GroupViewHolderholder=newGroupViewHolder();
- holder.mGroupName=(TextView)convertView
- .findViewById(R.id.group_name);
- holder.mGroupName.setText(mGroupStrings[groupPosition]);
- holder.mGroupCount=(TextView)convertView
- .findViewById(R.id.group_count);
- holder.mGroupCount.setText("["+mData.get(groupPosition).size()+"]");
- returnconvertView;
- }
- @Override
- publicViewgetChildView(intgroupPosition,intchildPosition,
- booleanisLastChild,ViewconvertView,ViewGroupparent){
- //TODOAuto-generatedmethodstub
- if(convertView==null){
- convertView=mInflater.inflate(R.layout.child_item_layout,null);
- }
- ChildViewHolderholder=newChildViewHolder();
- holder.mIcon=(ImageView)convertView.findViewById(R.id.img);
- holder.mIcon.setBackgroundDrawable(getRoundCornerDrawable(
- getChild(groupPosition,childPosition).getImageId(),10));
- holder.mChildName=(TextView)convertView.findViewById(R.id.item_name);
- holder.mChildName.setText(getChild(groupPosition,childPosition)
- .getName());
- holder.mDetail=(TextView)convertView.findViewById(R.id.item_detail);
- holder.mDetail.setText(getChild(groupPosition,childPosition)
- .getDetail());
- returnconvertView;
- }
- @Override
- publicbooleanisChildSelectable(intgroupPosition,intchildPosition){
- //TODOAuto-generatedmethodstub
- /*很重要:实现ChildView点击事件,必须返回true*/
- returntrue;
- }
- privateDrawablegetRoundCornerDrawable(intresId,floatroundPX/*圆角的半径*/){
- Drawabledrawable=mContext.getResources().getDrawable(resId);
- intw=mContext.getResources().getDimensionPixelSize(R.dimen.image_width);
- inth=w;
- Bitmapbitmap=Bitmap
- .createBitmap(w,h,
- drawable.getOpacity()!=PixelFormat.OPAQUE?Bitmap.Config.ARGB_8888
- :Bitmap.Config.RGB_565);
- Canvascanvas=newCanvas(bitmap);
- drawable.setBounds(0,0,w,h);
- drawable.draw(canvas);
- intwidth=bitmap.getWidth();
- intheight=bitmap.getHeight();
- BitmapretBmp=Bitmap.createBitmap(width,height,Config.ARGB_8888);
- Canvascan=newCanvas(retBmp);
- finalintcolor=0xff424242;
- finalPaintpaint=newPaint();
- finalRectrect=newRect(0,0,width,height);
- finalRectFrectF=newRectF(rect);
- paint.setColor(color);
- paint.setAntiAlias(true);
- can.drawARGB(0,0,0,0);
- can.drawRoundRect(rectF,roundPX,roundPX,paint);
- paint.setXfermode(newPorterDuffXfermode(Mode.SRC_IN));
- can.drawBitmap(bitmap,rect,rect,paint);
- returnnewBitmapDrawable(retBmp);
- }
- privateclassGroupViewHolder{
- TextViewmGroupName;
- TextViewmGroupCount;
- }
- privateclassChildViewHolder{
- ImageViewmIcon;
- TextViewmChildName;
- TextViewmDetail;
- }
- }
- </span>
布局group_item_layout.xml如下:
[html] view plain copy
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:orientation="horizontal">
- <TextView
- android:id="@+id/group_name"
- android:layout_width="wrap_content"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginLeft="35dip"
- android:gravity="center_vertical"
- android:singleLine="true"/>
- <TextView
- android:id="@+id/group_count"
- android:layout_width="wrap_content"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginLeft="5dip"
- android:gravity="center_vertical"
- android:singleLine="true"/>
- </LinearLayout>
另外一个就是ChildView,本例仿QQ好友列表,如图:
哈哈,熟悉吧。布局child_item_layout.xml如下:
[html] view plain copy
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/min_Height"
- <spanstyle="color:#ff0000;">android:descendantFocusability="blocksDescendants"
- </span>android:orientation="horizontal">
- <ImageView
- android:id="@+id/img"
- android:layout_width="@dimen/image_width"
- android:layout_height="@dimen/image_width"
- android:layout_marginLeft="2dip"
- android:layout_marginRight="10dip"
- android:layout_gravity="center_vertical"/>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <TextView
- android:id="@+id/item_name"
- android:layout_width="wrap_content"
- android:layout_height="0.0dip"
- android:gravity="center_vertical"
- android:layout_weight="1"/>
- <TextView
- android:id="@+id/item_detail"
- android:layout_width="wrap_content"
- android:layout_height="0.0dip"
- android:gravity="center_vertical"
- android:singleLine="true"
- android:ellipsize="end"
- android:layout_weight="1"/>
- </LinearLayout>
- </LinearLayout>
适配器弄好了,ExpandableListView就用系统的,现在只剩下显示的问题啦
先来几张效果图:
主Activity如下:
[java] view plain copy
- packagecom.xyz.expande;
- importjava.util.ArrayList;
- importjava.util.List;
- importandroid.app.Activity;
- importandroid.app.AlertDialog;
- importandroid.content.DialogInterface;
- importandroid.content.DialogInterface.OnClickListener;
- importandroid.os.Bundle;
- importandroid.view.View;
- importandroid.view.ViewGroup.LayoutParams;
- importandroid.widget.ExpandableListView;
- importandroid.widget.ExpandableListView.OnChildClickListener;
- publicclassHomeActivityextendsActivityimplementsOnChildClickListener{
- privateExpandableListViewmListView=null;
- privateExpandeAdaptermAdapter=null;
- privateList<List<Item>>mData=newArrayList<List<Item>>();
- privateint[]mGroupArrays=newint[]{
- R.array.tianlongbabu,
- R.array.shediaoyingxiongzhuan,
- R.array.shendiaoxialv};
- privateint[]mDetailIds=newint[]{
- R.array.tianlongbabu_detail,
- R.array.shediaoyingxiongzhuan_detail,
- R.array.shendiaoxialv_detail};
- privateint[][]mImageIds=newint[][]{
- {R.drawable.img_00,
- R.drawable.img_01,
- R.drawable.img_02},
- {R.drawable.img_10,
- R.drawable.img_11,
- R.drawable.img_12,
- R.drawable.img_13,
- R.drawable.img_14,
- R.drawable.img_15,
- R.drawable.img_16},
- {R.drawable.img_20,
- R.drawable.img_21}};
- /**Calledwhentheactivityisfirstcreated.*/
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- initData();
- mListView=newExpandableListView(this);
- mListView.setLayoutParams(newLayoutParams(LayoutParams.FILL_PARENT,
- LayoutParams.FILL_PARENT));
- setContentView(mListView);
- mListView.setGroupIndicator(getResources().getDrawable(
- R.drawable.expander_floder));
- mAdapter=newExpandeAdapter(this,mData);
- mListView.setAdapter(mAdapter);
- mListView.setOnChildClickListener(this);
- }
- <spanstyle="color:#ff0000;">/*
- *ChildView设置布局很可能onChildClick进不来,要在ChildViewlayout里加上
- *android:descendantFocusability="blocksDescendants",
- *还有isChildSelectable里返回true
- */
- </span>@Override
- publicbooleanonChildClick(ExpandableListViewparent,Viewv,
- intgroupPosition,intchildPosition,longid){
- //TODOAuto-generatedmethodstub
- Itemitem=mAdapter.getChild(groupPosition,childPosition);
- newAlertDialog.Builder(this)
- .setTitle(item.getName())
- .setMessage(item.getDetail())
- .setIcon(android.R.drawable.ic_menu_more)
- .setNegativeButton(android.R.string.cancel,
- newOnClickListener(){
- @Override
- publicvoidonClick(DialogInterfacedialog,
- intwhich){
- //TODOAuto-generatedmethodstub
- }
- }).create().show();
- returntrue;
- }
- privatevoidinitData(){
- for(inti=0;i<mGroupArrays.length;i++){
- List<Item>list=newArrayList<Item>();
- String[]childs=getStringArray(mGroupArrays[i]);
- String[]details=getStringArray(mDetailIds[i]);
- for(intj=0;j<childs.length;j++){
- Itemitem=newItem(mImageIds[i][j],childs[j],details[j]);
- list.add(item);
- }
- mData.add(list);
- }
- }
- privateString[]getStringArray(intresId){
- returngetResources().getStringArray(resId);
- }
- }
写这个demo的时候,想实现ChildView的点击事件,实现接口onChildClick,发现不进来,很尴尬。。。最后还是在网上找到答案了,第一,在适配器里isChildSelectable 必须返回true,第二,ChildView布局child_item_layout.xml最外层的layout设置个属性:
[java] view plain copy
- <spanstyle="FONT-SIZE:14px"><spanxmlns="http://www.w3.org/1999/xhtml"><spanxmlns="http://www.w3.org/1999/xhtml"><spanxmlns="http://www.w3.org/1999/xhtml"><spanxmlns="http://www.w3.org/1999/xhtml">android:descendantFocusability="blocksDescendants"</span></span></span></span></span>
细心的同学会发现 Item 是啥?也贴出来吧
[java] view plain copy
- packagecom.xyz.expande;
- publicclassItem{
- privateintresId;
- privateStringname;
- privateStringdetail;
- publicItem(intresId,Stringname,Stringdetail){
- this.resId=resId;
- this.name=name;
- this.detail=detail;
- }
- publicvoidsetImageId(intresId){
- this.resId=resId;
- }
- publicintgetImageId(){
- returnresId;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- }
- publicStringgetName(){
- returnname;
- }
- publicvoidsetDetail(Stringdetail){
- this.detail=detail;
- }
- publicStringgetDetail(){
- returndetail;
- }
- publicStringtoString(){
- return"Item["+resId+","+name+","+detail+"]";
- }
- }
有不对的地方请指正,互相学习!(ChildView左边的图片处理成圆角:请看函数getRoundCornerDrawable:具体细节请看:Android --- 图片的特效处理
免分下载源码路径:http://download.csdn.net/detail/zhouyuanjing/4843520
~~完~~更多相关文章
- 室内定位导航系统设计实现指南
- [Android]Android(安卓)FTP server based on Apache FTPServer
- 关于android读取用户号码,手机串号,SIM卡序列号
- Xposed框架之函数Hook学习
- 自定义实现简单的Android颜色选择器(附带源码)
- Android调用WebService之服务端实现(一)
- Android中activity切换动画的两种实现(附种17种动画效果)
- Android(安卓)API Demos学习(1) - Hello World
- 浅谈Java中Collections.sort对List排序的两种方法