今天想和大家分享的是QQ好友列表的实现,我们知道,在默认情况下,QQ好友列表是处于收缩状态的,此时,列表显示好友分组名称。当我们单击分组时,列表处于展开状态,列表显示该分组下的项目。当再次单击分组时,列表恢复到收缩状态。

首先想和大家说说实现QQ好友列表的原理,我们给每个ListView的项目中嵌套一个ListView,默认情况下嵌套的ListView(子控件)是隐藏的,当单击ListView(父控件)时,嵌套的ListView(子控件)将显示出来,并显示该分组下的项目。

接下来我们我们定义几个主要的类:Group、GroupItem、GroupItemAdapter、FriendViewAdapter。其中,Group类用于描述好友分组结构、GroupItem类用于描述好友结果、GroupItemAdapter是好友的数据适配器、FriendViewAdapter是分组的数据适配器,下面我们来分别讲述它们。

1、Group类封装了分组的标题和分组内的数据,定义如下:

package com.android.Mobile.QQ.FriendsView;

import java.util.List;

public class Group 
{
   //分组名称
   private String mGroupName;
   //分组项目
   private List<GroupItem> mGroupItems;
   
   public Group(String GroupName,List<GroupItem> GroupItems)
   {
	   this.mGroupName=GroupName;
	   this.mGroupItems=GroupItems;
   }

   public String getGroupName() {
	return mGroupName;
   }

   public void setGroupName(String mGroupName) {
	this.mGroupName = mGroupName;
   }

   public List<GroupItem> getGroupItems() {
	return mGroupItems;
   }

   public void setGroupItems(List<GroupItem> mItems) {
	this.mGroupItems = mItems;
   }
}

2、GroupItem类用于描述分组内的项目,定义如下:

package com.android.Mobile.QQ.FriendsView;

public class GroupItem 
{
   private String Title;
   private String Content;
   
   public GroupItem(String mTitle,String mContent)
   {
	   this.Title=mTitle;
	   this.Content=mContent;
   }
   
   
   public String getTitle() {
	return Title;
   }
   public void setTitle(String title) {
	Title = title;
   }
   public String getContent() {
	return Content;
   }
   public void setContent(String content) {
	Content = content;
  }
}

3、GroupItemAdapter适配器类:

package com.android.Mobile.QQ.FriendsView;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class GroupItemAdapter extends BaseAdapter {

	private Context mContext;
	private List<GroupItem> mItems;
	
	public GroupItemAdapter(Context mContext,List<GroupItem> mItems)
	{
		this.mContext=mContext;
		this.mItems=mItems;
	}
	@Override
	public int getCount() 
	{
		return mItems.size();
	}

	@Override
	public Object getItem(int Index) 
	{
		return mItems.get(Index);
	}

	@Override
	public long getItemId(int Index) 
	{
		return Index;
	}

	@Override
	public View getView(int Index, View mView, ViewGroup mParent) 
	{
		mView=LayoutInflater.from(mContext).inflate(R.layout.layout_group_item, null);
		//绑定好友结构中的Title
		((TextView)mView.findViewById(R.id.Group_Item_Title)).setText(mItems.get(Index).getTitle());
		//绑定好友结构中的Content
		((TextView)mView.findViewById(R.id.Group_Item_Content)).setText(mItems.get(Index).getContent());
		return mView;
	}

}

4、主适配器类FriendViewAdapter

package com.android.Mobile.QQ.FriendsView;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

public class FriendViewAdapter extends BaseAdapter {

	private Context mContext;
	private List<Group> mGroups;
	private boolean isShowGroupItem=false;
	
	public FriendViewAdapter(Context mContext,List<Group> mGroups)
	{
		this.mContext=mContext;
		this.mGroups=mGroups;
	}
	
	@Override
	public int getCount() 
	{
		return mGroups.size();
	}

	@Override
	public Object getItem(int Index) 
	{
		return mGroups.get(Index);
	}

	@Override
	public long getItemId(int Index) 
	{
		return Index;
	}

	@Override
	public View getView(final int Index, View mView, ViewGroup mParent) 
	{
		mView=LayoutInflater.from(mContext).inflate(R.layout.layout_group, null);
		//设置分组的名称
		((TextView)mView.findViewById(R.id.Group_GroupName)).setText(mGroups.get(Index).getGroupName());
		//设置分组容量
		String mItemsCount=String.valueOf(mGroups.get(Index).getGroupItems().size());
		((TextView)mView.findViewById(R.id.Group_ItemCount)).setText(mItemsCount);
		//设置分组下的列表
	    final ListView ItemsList=(ListView)mView.findViewById(R.id.GroupItemList);
	    GroupItemAdapter mAdapter=new GroupItemAdapter(mContext, mGroups.get(Index).getGroupItems());
		ItemsList.setAdapter(mAdapter);
		ItemsList.setOnItemClickListener(new OnItemClickListener()
		{
			@Override
			public void onItemClick(AdapterView<?> adapter, View view, int index,long id)
			{
				Toast.makeText(mContext, "Item "+index+" Click!", Toast.LENGTH_LONG).show();
			}
		});
		//设置分组小的列表高度
		setGroupHeight(ItemsList);
		//给分组添加Click事件
        final RelativeLayout GroupLayout=(RelativeLayout)mView.findViewById(R.id.GroupLayout);
        GroupLayout.setOnClickListener(new OnClickListener()
        {
             @Override
             public void onClick(View v) 
            {
               if(!isShowGroupItem)
               {
                  ItemsList.setVisibility(View.VISIBLE);
                  GroupLayout.setBackgroundResource(R.drawable.group_bg_open);
                  isShowGroupItem=true;
               }
               else
              {
                 ItemsList.setVisibility(View.GONE);
                 GroupLayout.setBackgroundResource(R.drawable.grop_bg_close);
                 isShowGroupItem=false;
              }
           }
       });
		return mView;
	}

	/*
	 * 这是一个神奇的方法,在所有的View嵌套问题中都需要解决这个问题
	 */
	private void setGroupHeight(ListView mListView)
	{
		int mTotalHeight=0;
		ListAdapter mAdapter=mListView.getAdapter();
		for(int i=0;i<mAdapter.getCount();i++)
		{
			View ItemView=mAdapter.getView(i, null, mListView);
			ItemView.measure(0, 0);
			mTotalHeight+=ItemView.getMeasuredHeight();
		}
		ViewGroup.LayoutParams mParams=mListView.getLayoutParams();
		mParams.height=mTotalHeight;
		mListView.setMinimumHeight(mTotalHeight);
	}
}

程序运行效果:

Android studio做QQ好友列表 安卓实现qq好友列表_移动开发

Android studio做QQ好友列表 安卓实现qq好友列表_android_02

两点总结:

1、自定义ListView无法响应OnItemClick事件的解决方案是将自定义布局的根节点属性android:descendantFocusability设置为blocksDescendants,这样嵌套的子控件可以取得焦点,响应响应的操作。

2、嵌套子控件时,需要使用下面的方法根据子控件的内容重新设置父控件的高度,否则子控件会出现显示不全的问题:

/*
	 * 这是一个神奇的方法,在所有的View嵌套问题中都需要解决这个问题
	 */
	private void setGroupHeight(ListView mListView)
	{
		int mTotalHeight=0;
		ListAdapter mAdapter=mListView.getAdapter();
		for(int i=0;i<mAdapter.getCount();i++)
		{
			View ItemView=mAdapter.getView(i, null, mListView);
			ItemView.measure(0, 0);
			mTotalHeight+=ItemView.getMeasuredHeight();
		}
		ViewGroup.LayoutParams mParams=mListView.getLayoutParams();
		mParams.height=mTotalHeight;
		mListView.setMinimumHeight(mTotalHeight);
	}