项目中用到了多级的目录,我因此自己参考了些资料并去总结了写RecyclerView多级条目的方式!写下自己的总结。
实现方式不外乎两种:
1,多级嵌套recyclerview
2,多种Type的item的实现方式
一,第一种我们是经常用到,两级嵌套的时候感觉很好使用,但是嵌套的级数更多的话,实现起来也就麻烦了,特别是三级或者更多级的时候,你会写到欲仙欲死的!
二,第二种就是我们常用的多种Type的条目,使用方式很多种,满足各种需求!
以下两种情况适合你大多数的项目的!当然,你要自己看,也就能自己很随意写出RecyclerView的多级目录了
1),这里我实现 省 与 城市的选择的多级
这里是比较少的数据,而且这里的数据都是默认展开的!已经实现单一条目的 单选!!!
public class SearchPositionSortAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
public static final int TYPE_TITLE = 0;
public static final int TYPE_CITY = 1;
private SparseArray<SelectBean> mSparseArray;
private final Context context;
private List<String> cityTitle;// 城市拼音字母数据
private List<List<String>> cityNames;
// 传入两个集合,这里你根据自己需要参数
// 第一个参数为第一级目录,第二个参数为第二级目录
public SearchPositionSortAdapter(Context context, List<String> cityTitle, List<List<String>> map) {
this.context = context;
this.cityTitle = cityTitle;
cityNames = map;
mSparseArray = new SparseArray<>();
}
private SparseArray getCurrentChooseItem() {
return mSparseArray;
}
@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_TITLE:
return new CityTitleHolder(R.layout.item_choose_location_title, parent, viewType, 100);
case TYPE_CITY:
return new CityNameHolder(R.layout.item_choose_location_cityname, parent, viewType);
}
return null;
}
@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
if (holder instanceof CityNameHolder) {
holder.refreshData(cityNames.get(position / 2), position);
} else if (holder instanceof CityTitleHolder) {
holder.refreshData(cityTitle.get(position / 2), position);
}
}
@Override
public int getItemCount() {
return cityTitle.size() * 2;
}
@Override
public int getItemViewType(int position) {
if (position % 2 == 0) {
return TYPE_TITLE;
} else {
return TYPE_CITY;
}
}
// ===================ViewHolder======================
/**
* GridView形状的RecyclerView
*/
class CityNameHolder extends ExampleViewHolder<List<String>> {
RecyclerView revCityname;
private List<String> data;
public CityNameHolder(int viewId, ViewGroup parent, int viewType) {
super(viewId, parent, viewType);
this.revCityname = (RecyclerView) itemView.findViewById(R.id.rev_cityname);
}
@Override
public void refreshData(List<String> data, int position) {
super.refreshData(data, position);
this.data = data;
revCityname.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
// 某一行的id
GridAdapter gridAdapter = new GridAdapter(position);
revCityname.setAdapter(gridAdapter);
}
private class GridAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
// 这一行的 id
private int CurrenIndex;
public GridAdapter(int Currentpos) {
super();
this.CurrenIndex = Currentpos;
}
@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final CityTitleHolder cityTitleHolder = new CityTitleHolder(R.layout.item_gridview_cityname, parent, viewType, CurrenIndex);
cityTitleHolder.title.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 拿到当前的 对象
SelectBean mSelectbean = new SelectBean(cityTitleHolder.getAdapterPosition(), cityTitleHolder.title.getText().toString());
// 没有选中的
if (mSparseArray.get(CurrenIndex) == null) {
mSparseArray.put(CurrenIndex, mSelectbean);
} else { // 有选中的
if (mSparseArray.get(CurrenIndex).equals(mSelectbean)) {
mSparseArray.remove(CurrenIndex);
} else {
mSparseArray.remove(CurrenIndex);
mSparseArray.put(CurrenIndex, mSelectbean);
}
}
// 点击完首先当前界面
notifyDataSetChanged();
}
});
return cityTitleHolder;
}
@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
holder.refreshData(data.get(position), position);
}
@Override
public int getItemCount() {
return data.size();
}
}
}
/**
* 普通条目hodler
*/
private class CityTitleHolder extends ExampleViewHolder<String> {
// 当前行的index ;
private int CurrentIndex;
private TextView title;
public CityTitleHolder(int viewId, ViewGroup parent, int viewType, int posIndex) {
super(viewId, parent, viewType);
title = (TextView) itemView.findViewById(R.id.title);
CurrentIndex = posIndex;
// ViewGroup.LayoutParams layoutParams = title.getLayoutParams();
// layoutParams.width = layoutParams.height = DisplayUtil.getScreenWidth(context) / 3;
// title.setLayoutParams(layoutParams);
}
//if (mSparseArray.get(CurrentIndex).getCurrentPos() == position && mSparseArray.get(CurrentIndex).getCurrentData().equals(data))
@Override
public void refreshData(String data, int position) {
super.refreshData(data, position);
if (CurrentIndex % 2 == 1) {
if (mSparseArray.get(CurrentIndex) != null && mSparseArray.get(CurrentIndex).equals(new SelectBean(position, data))) {
title.setTextColor(context.getResources().getColor(R.color.app_focus));
title.setBackgroundResource(R.drawable.shape_gridview_item_select);
} else {
title.setTextColor(context.getResources().getColor(R.color.text_color2));
title.setBackgroundResource(R.drawable.shape_gridview_item);
}
/* if (mSparseArray.get(CurrentIndex) == null) {
title.setTextColor(context.getResources().getColor(R.color.text_color2));
title.setBackgroundResource(R.drawable.shape_gridview_item);
} else {
}*/
}
title.setText(data);
// mSparseArray.
}
}
}
2),这里实现的专业选择大全,这里是三级目录的实现其实和上面实现原理差不多一致! 这里最烦的是数据结构,我随便写了个简单的格式,你参照这个格式和服务器的哥们讨论吧
这里是可对应多种的数据结构,灵活多变!易于改造!因为我是先写的上面,再写的这个Adapter,不然这个完全够使用任何的形式(单选,多选,动画弹出)的adapter!
数据结构
/**
* @data 2017/4/12 0012
* @aurher Administrator
*/
public class ThreeItemInfo {
private String status = "1";
private boolean isExpading ;
private List<ThreeItemInfo> results = new ArrayList<>();
public boolean getIsExpading(){
return isExpading ;
}
public void setIsExpading(boolean isExpading){
this.isExpading = isExpading ;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public List<ThreeItemInfo> getResults() {
return results;
}
public void setResults(List<ThreeItemInfo> results) {
this.results = results;
}
}
模拟数据
mList = new ArrayList<>();
for (int i = 0; i <= 5; i++) {
ThreeItemInfo threeItemInfo = new ThreeItemInfo();
threeItemInfo.setStatus("1");
if (i % 2 == 0) {
List<ThreeItemInfo> itemInfos = new ArrayList<>();
for (int j = 0; j <= 5; j++) {
ThreeItemInfo threeItemInfo_2 = new ThreeItemInfo();
threeItemInfo_2.setStatus("2");
itemInfos.add(threeItemInfo_2);
if (j % 2 == 0) {
List<ThreeItemInfo> itemInfos_list = new ArrayList<>();
for (int z = 0; z <= 5; z++) {
ThreeItemInfo threeItemInfo_3 = new ThreeItemInfo();
threeItemInfo_3.setStatus("3");
itemInfos_list.add(threeItemInfo_3);
}
// 二级目录的添加
threeItemInfo_2.setResults(itemInfos_list);
}
}
// 二级目录的添加
threeItemInfo.setResults(itemInfos);
}
// 添加一级目录
mList.add(threeItemInfo);
}
public class ThreeItemAdapter extends MultiItemRecycleViewAdapter<ThreeItemInfo> {
private static final int TYPE_ONE = 0;
private static final int TYPE_TWO = 1;
private static final int TYPE_THREE = 2;
public ThreeItemAdapter(Context context, List<ThreeItemInfo> datas) {
super(context, datas, new MultiItemTypeSupport<ThreeItemInfo>() {
@Override
public int getLayoutId(int itemType) {
int i = 0;
switch (itemType) {
case TYPE_ONE:
i = R.layout.item_one_threeitem;
break;
case TYPE_TWO:
i = R.layout.item_two_threeitem;
break;
case TYPE_THREE:
i = R.layout.item_three_threeitem;
break;
}
return i;
}
@Override
public int getItemViewType(int position, ThreeItemInfo threeItemInfo) {
String currentCity = threeItemInfo.getStatus();
int i = 0;
switch (currentCity) {
case "1":
i = TYPE_ONE;
break;
case "2":
i = TYPE_TWO;
break;
case "3":
i = TYPE_THREE;
break;
}
return i;
}
});
}
@Override
public void convert(ViewHolderHelper helper, ThreeItemInfo threeItemInfo, int position) {
switch (helper.getLayoutId()) {
case R.layout.item_one_threeitem:
bindViewOne(helper, threeItemInfo, position);
break;
case R.layout.item_two_threeitem:
bindViewTwo(helper, threeItemInfo, position);
break;
case R.layout.item_three_threeitem:
bindViewThree(helper, threeItemInfo, position);
break;
}
}
private void bindViewOne(ViewHolderHelper helper, final ThreeItemInfo threeItemInfo, final int position) {
TextView tv_1 = helper.getView(R.id.tv_1);
helper.getConvertView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.logd("我被点击了");
LogUtils.logd("我被点击了----" + (threeItemInfo.getResults()) + "-----" + threeItemInfo.getResults().size() + "---------" + threeItemInfo.getIsExpading());
if (threeItemInfo.getResults() != null && threeItemInfo.getResults().size() != 0 && threeItemInfo.getIsExpading()) {
addAllAt(position + 1, threeItemInfo.getResults());
threeItemInfo.setIsExpading(false);
} else if (threeItemInfo.getResults() != null & threeItemInfo.getResults().size() != 0 && !threeItemInfo.getIsExpading()) {
for (ThreeItemInfo item : threeItemInfo.getResults()) {
if (!item.getIsExpading()) {
removeAll(item.getResults());
}
}
removeAll(threeItemInfo.getResults());
threeItemInfo.setIsExpading(true);
}
}
});
}
private void bindViewTwo(ViewHolderHelper helper, final ThreeItemInfo threeItemInfo, final int position) {
TextView tv_2 = helper.getView(R.id.tv_2);
helper.getConvertView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (threeItemInfo.getResults() != null && threeItemInfo.getResults().size() != 0 && threeItemInfo.getIsExpading()) {
addAllAt(position + 1, threeItemInfo.getResults());
threeItemInfo.setIsExpading(false);
} else if (threeItemInfo.getResults() != null & threeItemInfo.getResults().size() != 0 && !threeItemInfo.getIsExpading()) {
removeAll(threeItemInfo.getResults());
threeItemInfo.setIsExpading(true);
}
}
});
}
private void bindViewThree(ViewHolderHelper helper, ThreeItemInfo threeItemInfo, final int position) {
TextView tv_3 = helper.getView(R.id.tv_3);
helper.getConvertView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.logd("我被点击了" + "我是第三个条目" + position);
if (onItemThreeClickListener != null) {
onItemThreeClickListener.ThreeOnclickListener(position);
}
}
});
}
public interface OnItemThreeClickListener {
void ThreeOnclickListener(int position);
}
private OnItemThreeClickListener onItemThreeClickListener;
public void setOnItemThreeClickListener(OnItemThreeClickListener onItemThreeClickListener) {
this.onItemThreeClickListener = onItemThreeClickListener;
}
}
可能上面没写得很清楚,我附带源码上传吧!
封装了完整的Adapter,已经自己单独写了第一gif的截图!希望能帮到你写多级目录(第二个Gif是默认生成的)
DemoAdapter