实现的效果类似于QQ好友列表,点击可展开,再次点击收起:
两个Item的布局都很简单,这里就不给布局代码了。值得一提的是,RecyclerView
本身并没有ListView
那样的点击效果,想要类似效果可以为Item的根布局写个Selector,然后设置android:clickable="true"
。
接下来就是两个实体类,也比较简单:
public class ContactGroup {
private String groupName;
private boolean isExpand;
private List<ContactInfo> contacts;
}
public class ContactInfo {
private int imageResId;
private String nickname;
private String description;
}
最后是Adapter
的实现,由于有两个不同Item,我们选择数据源为Object
的容器,然后再根据元素的类型来载入不同的布局,代码如下:
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ContactsViewHolder>
implements View.OnClickListener {
private Context mContext;
private List<Object> mData;
private RecyclerView mRvContacts;
public ContactsAdapter(Context context, List<Object> data) {
mContext = context;
mData = data;
}
/**
* 该方法返回值可以为任意值,直接返回需要绑定的Item布局id,
* 这样在绑定视图时就不用对类型进行判断,拿到入参viewType即可。
*/
@Override
public int getItemViewType(int position) {
int ret = 0;
if (mData.get(position) instanceof ContactGroup) {
ret = R.layout.item_group_contacts;
}
if (mData.get(position) instanceof ContactInfo) {
ret = R.layout.item_contacts;
}
return ret;
}
@Override
public ContactsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(viewType, parent, false);
view.setOnClickListener(this);
return new ContactsViewHolder(view);
}
@Override
public void onBindViewHolder(ContactsViewHolder holder, int position) {
switch (getItemViewType(position)) {
case R.layout.item_group_contacts:
ContactGroup group = (ContactGroup) mData.get(position);
holder.tvGroupName.setText(group.getGroupName());
break;
case R.layout.item_contacts:
ContactInfo contact = (ContactInfo) mData.get(position);
holder.ivAvatar.setImageResource(contact.getImageResId());
holder.tvNickname.setText(contact.getNickname());
holder.tvDescription.setText(contact.getDescription());
break;
}
}
@Override
public int getItemCount() {
return mData.size();
}
/**
* 拿到与当前Adapter绑定的RecyclerView
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
mRvContacts = recyclerView;
}
/**
* 首先拿到当前的点击位置,然后通过判断当前Item的数据类型进行操作
*/
@Override
public void onClick(View v) {
int position = mRvContacts.getChildAdapterPosition(v);
Object o = mData.get(position);
if (o instanceof ContactGroup) {
ContactGroup contactGroup = (ContactGroup) o;
// 展开收起时,分组头部的小三角形状态会有改变,这里拿到当前位置的ViewHolder对象
ContactsViewHolder holder = (ContactsViewHolder) mRvContacts.getChildViewHolder(v);
if (contactGroup.isExpand()) {
// 从当前位置的底部移除已展开的好友列表,更新isExpand,最后再改变小三角形的状态
removeAll(position + 1, contactGroup.getContacts());
contactGroup.setExpand(false);
holder.ivIsExpand.setImageResource(R.drawable.triangle_right);
} else {
addAll(contactGroup.getContacts());
contactGroup.setExpand(true);
holder.ivIsExpand.setImageResource(R.drawable.triangle_bottom);
}
} else if (o instanceof ContactInfo) {
ContactInfo contactInfo = (ContactInfo) o;
ToastUtils.show(mContext, contactInfo.getNickname());
}
}
public void addAll(int position, Collection data) {
mData.addAll(position, data);
notifyDataSetChanged();
}
public void removeAll(Collection data) {
mData.removeAll(data);
notifyDataSetChanged();
}
public class ContactsViewHolder extends RecyclerView.ViewHolder {
TextView tvGroupName;
ImageView ivIsExpand;
ImageView ivAvatar;
TextView tvNickname;
TextView tvDescription;
public ContactsViewHolder(View itemView) {
super(itemView);
tvGroupName = (TextView) itemView.findViewById(R.id.tv_contacts_group_name);
ivIsExpand = (ImageView) itemView.findViewById(R.id.iv_is_expand);
ivAvatar = (ImageView) itemView.findViewById(R.id.iv_avatar);
tvNickname = (TextView) itemView.findViewById(R.id.tv_nickname);
tvDescription = (TextView) itemView.findViewById(R.id.tv_description);
}
}
}
如果需要实现带动画效果的展开与收齐,只需要替换几行代码即可:
public void addAll(int position, Collection data) {
mData.addAll(position, data);
notifyItemRangeInserted(position, data.size());
}
public void removeAll(int position, Collection data) {
mData.removeAll(data);
notifyItemRangeChanged(position, data.size());
}
默认的动画效果如下:
如果需要修改默认的动画效果,可以参考我的这篇文章:RecyclerView详解 —— 自定义动画