第三方框架AndroidTreeView官方网址Github Demo其中使用到一个 第三方图标框架Print 。
不使用图标库框架Print(因为不需要)。
分析第三方框架AndroidTreeView:
每一层使用LinearLayout添加内部节点(TreeNodeWrapperView)。
默认显示所有年级名称;点击某一个年级,加载其所有班级名称;点击某一班级,加载其所有学生名称。年级、班级单选,学生可多选。选择的项文字变红,没选择的是黑色。相应的箭头会根据状态改变。
因为功能需求,在library的AndroidTreeView中新增了一个方法:
//新增函数:只展开自己;收缩自己及子节点
public void toggleNode(TreeNode node,boolean includeSubnodes) {
if (node.isExpanded()) {
collapseNode(node, includeSubnodes);//收缩所有,包括子节点
} else {
expandNode(node, false);//只展开自己
}
}
功能逻辑处理整个过程
public class MoreListFragment extends Fragment {
private TextView tvShow;
private ViewGroup containerView;
private AndroidTreeView tView;
private TreeNode choseGradeNode;//已选的年级节点
private String choseGradeStr;//已选的年级值
private List initGradeList = new ArrayList<>();//已初始化班级节点的年级
private TreeNode choseClassNode;//已选的班级节点
private String choseClassStr;//已选的班级值
private List initClassList = new ArrayList<>();//已初始化学生节点的班级
private List choseStudentList = new ArrayList<>();//已选的学生值
private int nodeCount = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_default, null, false);
containerView = (ViewGroup) rootView.findViewById(R.id.container);
tvShow = (TextView) rootView.findViewById(R.id.status_bar);
initGradeNodes();
return rootView;
}
/**
* 初始化年级节点
*/
private void initGradeNodes(){
TreeNode root = TreeNode.root();
for (int i = 0; i < 3; i++) {
TreeNode areaNode = new TreeNode(new TreeNodeHolder.IconTreeItem("grade_" + i, "" + nodeCount,0));
nodeCount++;
root.addChildren(areaNode);
}
tView = new AndroidTreeView(getActivity(), root);
tView.setDefaultAnimation(true);
tView.setUseAutoToggle(false);//不使用自动展开收缩
tView.setDefaultContainerStyle(R.style.TreeNodeStyleCustom);//TreeNodeStyleCustom、 TreeNodeStyleDivided
tView.setDefaultViewHolder(TreeNodeHolder.class);
tView.setDefaultNodeClickListener(nodeClickListener);
containerView.addView(tView.getView());
}
/**
* 初始化指定班级节点下的所有班级节点
* @param gradeNode 年级节点
*/
private void initClassNodes(TreeNode gradeNode){
for (int j = 0; j < 3; j++) {
TreeNode classNode = new TreeNode(new TreeNodeHolder.IconTreeItem("class_" + j, "" + nodeCount,1));
nodeCount++;
tView.addNode(gradeNode,classNode);
}
initGradeList.add(gradeNode);
}
/**
* 初始化指定班级节点下的所有学生节点
* @param classNode 班级节点
*/
private void initStudentNodes(TreeNode classNode){
for (int j = 0; j < 3; j++) {
TreeNode studentNode = new TreeNode(new TreeNodeHolder.IconTreeItem("student_" + j, "" + nodeCount,2));
nodeCount++;
tView.addNode(classNode,studentNode);
}
initClassList.add(classNode);
}
/**
* 多级树节点点击事件
*/
private TreeNode.TreeNodeClickListener nodeClickListener = new TreeNode.TreeNodeClickListener() {
@Override
public void onClick(TreeNode node, Object value) {
TreeNodeHolder.IconTreeItem item = (TreeNodeHolder.IconTreeItem) value;
switch (item.level){
case 0:
choseClassNode = null;
choseClassStr = "";
choseStudentList.clear();
if (choseGradeNode != null){//之前已选过节点
TreeNodeHolder.IconTreeItem choseAreaNodeValue = (TreeNodeHolder.IconTreeItem) choseGradeNode.getValue();
if (!item.id.equals(choseAreaNodeValue.id)) {
//此节点 != 上次选择的节点,则取消、收缩上次的节点及其子节点
tView.toggleNode(choseGradeNode, true);
}
}
choseGradeNode = node;
tView.toggleNode(node, true);//只展开此节点或收缩此节点及其子节点
if(node.isExpanded()){//选择此节点
choseGradeStr = item.text;
if(!initGradeList.contains(node)){//此节点还未初始化过子节点
initClassNodes(node);
}
}else {//取消此节点
choseGradeStr = "";
choseGradeNode = null;
}
break;
case 1:
choseStudentList.clear();
if (choseClassNode != null){//之前已选过节点
TreeNodeHolder.IconTreeItem choseHspNodeValue = (TreeNodeHolder.IconTreeItem) choseClassNode.getValue();
if (!item.id.equals(choseHspNodeValue.id)) {
//此节点 != 上次选择的节点,则取消、收缩上次的节点
tView.toggleNode(choseClassNode, true);
}
}
choseClassNode = node;
tView.toggleNode(node, true);//只展开此节点或收缩此节点及其子节点
if(node.isExpanded()){//选择此节点
choseClassStr = item.text;
if(!initClassList.contains(node)){//此节点还未初始化过子节点
initStudentNodes(node);
}
}else {//取消此节点
choseClassStr = "";
choseClassNode = null;
}
break;
case 2:
if(!choseStudentList.contains(item.text)){
choseStudentList.add(item.text);
}else {
choseStudentList.remove(item.text);
}
tView.toggleNode(node, true);
break;
}
tvShow.setText("["+choseGradeStr+"]_["+choseClassStr+"]_"+choseStudentList.toString());
}
};
}
public class TreeNodeHolder extends TreeNode.BaseNodeViewHolder {
private TextView tvValue;
private ImageView ivArrowIcon;
public TreeNodeHolder(Context context) {
super(context);
}
@Override
public View createNodeView(final TreeNode node, final IconTreeItem value) {
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.item_tree_node, null, false);
tvValue = (TextView) view.findViewById(R.id.node_value);
tvValue.setText(value.text);
ivArrowIcon = (ImageView) view.findViewById(R.id.iv_arrow_icon);
if (value.level == 2) {
ivArrowIcon.setVisibility(View.GONE);
}
return view;
}
@Override
public void toggle(boolean active) {
ivArrowIcon.setImageDrawable(context.getResources().getDrawable(active ? R.mipmap.ic_node_open:R.mipmap.ic_node_close));
tvValue.setTextColor(context.getResources().getColor(active ? R.color.text_red : R.color.text_black));
}
public static class IconTreeItem {
public String text;//文字
public String id;
public int level;
public IconTreeItem(String text,String id,int level) {
this.text = text;
this.id = id;
this.level = level;
}
}
}