简介
android是不提供树形控件的,如果需要使用树形控件,我们应该怎么做呢?
先看效果
上图是一个明显的树形结构
实现原理
在逻辑上,它们是包含关系,数据结构上是多叉树,这是毋庸置疑的。但是,显示的时候,我们有必要嵌套ListView或RecyclerView吗?当然没有必要!
- 每一而Item,在显示的时候,都是平级的,只是它们marginLeft不同而已。
- 更新marginLeft来体现它们的层级关系。marginLeft的值与item在逻辑上的深度有线性关系。
- 展开一个Item的时候,是动态的添加一系列的item。
- 收起一个Item的时候,我们是删除一系列的item.
好了,原理已经说明白了,那就看看源码怎么写吧。
注:
- 我们以android的文件系统的树形结构为例
- 为了动画的流畅性,我们使用RecyclerView,注意,ListView在添加和删除item时,是直接突变的。
Code
- 数据模型ItemData
public class ItemData implements Comparable<ItemData> {
public static final int ITEM_TYPE_PARENT = 0;
public static final int ITEM_TYPE_CHILD = 1;
private String uuid;
private int type;// 显示类型
private String text;
private String path;// 路径
private int treeDepth = 0;// 路径的深度
private List<ItemData> children;
private boolean expand;// 是否展开
...
}
- 父节点对应的ViewHolder
/**
* @Author Zheng Haibo
* @PersonalWebsite http://www.mobctrl.net
* @Description
*/
public class ParentViewHolder extends BaseViewHolder {
public ImageView image;
public TextView text;
public ImageView expand;
public TextView count;
public RelativeLayout relativeLayout;
private int itemMargin;
public ParentViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
text = (TextView) itemView.findViewById(R.id.text);
expand = (ImageView) itemView.findViewById(R.id.expand);
count = (TextView) itemView.findViewById(R.id.count);
relativeLayout = (RelativeLayout) itemView.findViewById(R.id.container);
itemMargin = itemView.getContext().getResources()
.getDimensionPixelSize(R.dimen.item_margin);
}
public void bindView(final ItemData itemData, final int position,
final ItemDataClickListener imageClickListener) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) expand
.getLayoutParams();
params.leftMargin = itemMargin * itemData.getTreeDepth();
expand.setLayoutParams(params);
text.setText(itemData.getText());
if (itemData.isExpand()) {
expand.setRotation(45);
List<ItemData> children = itemData.getChildren();
if (children != null) {
count.setText(String.format("(%s)", itemData.getChildren()
.size()));
}
count.setVisib