方法一:
Element.java :
package com.chy.ydy.tools.treeutil;
/**
* TreeView 元素
* */
public class Element {
/** 文字内容 */
private String contentText;
/** 在tree中的层级 */
private int level;
/** 元素的id */
private int id;
/** 父元素的id */
private int parendId;
/** 是否有子元素 */
private boolean hasChildren;
/** item是否展开 */
private boolean isExpanded;
/** 表示该节点没有父元素,也就是level为0的节点 */
public static final int NO_PARENT = -1;
/** 表示该元素位于最顶层的层级 */
public static final int TOP_LEVEL = 0;
/** 构造函数 */
public Element(String contentText, int level, int id, int parendId, boolean hasChildren, boolean isExpanded){
super();
this.contentText = contentText;
this.level = level;
this.id = id;
this.parendId = parendId;
this.hasChildren = hasChildren;
this.isExpanded = isExpanded;
}
public String getContentText() {
return contentText;
}
public void setContentText(String contentText) {
this.contentText = contentText;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getParendId() {
return parendId;
}
public void setParendId(int parendId) {
this.parendId = parendId;
}
public boolean isHasChildren() {
return hasChildren;
}
public void setHasChildren(boolean hasChildren) {
this.hasChildren = hasChildren;
}
public boolean isExpanded() {
return isExpanded;
}
public void setExpanded(boolean expanded) {
isExpanded = expanded;
}
}
TreeViewAdapter.java:
package com.chy.ydy.tools.treeutil;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.chy.ydy.R;
import java.util.ArrayList;
/**
* TreeView 适配器
* */
public class TreeViewAdapter extends BaseAdapter {
/** 元素数据源 */
private ArrayList<Element> elementsData;
/** 树中元素 */
private ArrayList<Element> elements;
/** LayoutInflater */
private Activity activity;
/** item的行首缩进基数 */
private int indentionBase;
/** 构造函数 */
public TreeViewAdapter(ArrayList<Element> elements, ArrayList<Element> elementsData, Activity activity) {
this.elements = elements;
this.elementsData = elementsData;
this.activity = activity;
indentionBase = 50;
}
/** 树中元素列表 */
public ArrayList<Element> getElements() {
return elements;
}
/** 元素数据源列表 */
public ArrayList<Element> getElementsData() {
return elementsData;
}
@Override
public int getCount() {
return elements.size();
}
@Override
public Object getItem(int position) {
return elements.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View contentView, ViewGroup parent) {
ViewHodler hodler = null;
if (contentView == null){
hodler = new ViewHodler();
LayoutInflater inflater = LayoutInflater.from(activity);
// 布局
contentView = inflater.inflate(R.layout.treeview_item,null);
hodler.prefixImg = contentView.findViewById(R.id.prefixImg);
hodler.contentText = contentView.findViewById(R.id.contentText);
contentView.setTag(hodler);
}else {
hodler = (ViewHodler) contentView.getTag();
}
Element element =elements.get(position); // 获取数据
int level = element.getLevel();// 获取该数据层级
// 设置前缀图片位置
hodler.prefixImg.setPadding(
indentionBase * (level+1),
hodler.prefixImg.getPaddingTop(),
hodler.prefixImg.getPaddingRight(),
hodler.prefixImg.getPaddingBottom());
// 设置内容
hodler.contentText.setText(element.getContentText());
// 判断是否有子集并且是否展开
if (element.isHasChildren() && !element.isExpanded()){// 设置关闭item前缀图片
// 设置图片为关闭
hodler.prefixImg.setImageResource(R.mipmap.ic_cancle);
//这里要主动设置一下icon可见,因为convertView有可能是重用了"设置了不可见"的view。
hodler.prefixImg.setVisibility(View.VISIBLE);
} else if (element.isHasChildren() && element.isExpanded()) {// 设置展开item前缀图片
// 设置图片为打开
hodler.prefixImg.setImageResource(R.mipmap.ic_down);
//这里要主动设置一下icon可见,因为convertView有可能是重用了"设置了不可见"的view。
hodler.prefixImg.setVisibility(View.VISIBLE);
} else if (!element.isHasChildren()) {// 设置没有子集的item前缀图片
// 设置图片为打开
hodler.prefixImg.setImageResource(R.mipmap.ic_cltd);
// 设置了不可见的view。
//hodler.prefixImg.setVisibility(View.VISIBLE);
// 设置了可见的view。
hodler.prefixImg.setVisibility(View.VISIBLE);
}
return contentView;
}
/**
* 优化Holder
* */
static class ViewHodler{
private ImageView prefixImg;// 前缀图片
private TextView contentText;// 内容
//private ImageView suffixImg;// 后缀图片
}
}
TreeViewItemClickListener.java:
package com.chy.ydy.tools.treeutil;
import android.view.View;
import android.widget.AdapterView;
import java.util.ArrayList;
/**
* TreeView item 点击事件
* */
public class TreeViewItemClickListener implements AdapterView.OnItemClickListener {
/** 没有子集item点击接口 */
protected TreeViewNoHasChildrenItemClick noHasChildrenItemClick;
/** adapter */
private TreeViewAdapter treeViewAdapter;
/** 构造函数 */
public TreeViewItemClickListener(TreeViewAdapter treeViewAdapter){
this.treeViewAdapter = treeViewAdapter;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//点击的item代表的元素
Element element = (Element) treeViewAdapter.getItem(position);
//树中的元素
ArrayList<Element> elements = treeViewAdapter.getElements();
//元素的数据源
ArrayList<Element> elementsData = treeViewAdapter.getElementsData();
/** 点击没有子项的item */
if (!element.isHasChildren()){
// 设置没有子集item点击接口参数
noHasChildrenItemClick.onTreeItemClick(position,element);
return;
}
/** 点击有子项的item */
if (element.isExpanded()){// 收缩
element.setExpanded(false);
// 删除节点内部对应子节点数据,包括子节点的字节点...
ArrayList<Element> elementsToDel = new ArrayList<Element>();
for (int i = position+1;i < elements.size(); i++){
if (element.getLevel() >= elements.get(i).getLevel())
break;
elementsToDel.add(elements.get(i));
}
elements.removeAll(elementsToDel);
treeViewAdapter.notifyDataSetChanged();
}else {// 展开
element.setExpanded(true);
//从数据源中提取子节点数据添加进树,注意这里只是添加了下一级子节点,为了简化逻辑
int i = 1;//注意这里的计数器放在for外面才能保证计数有效
for (Element e : elementsData){
if (e.getParendId() == element.getId()){
e.setExpanded(false);
elements.add(position+i,e);
i++;
}
}
treeViewAdapter.notifyDataSetChanged();
}
}
/**
* 设置点击事件
* */
public void setNoHasChildrenItemClick(TreeViewNoHasChildrenItemClick noHasChildrenItemClick) {
this.noHasChildrenItemClick = noHasChildrenItemClick;
}
/**
* 没有子类item点击事件接口
* */
public interface TreeViewNoHasChildrenItemClick {
void onTreeItemClick(int position, Element element);
}
}
实现代码:
package com.example.javademo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.ListView;
import com.example.javademo.tree.Element;
import com.example.javademo.tree.TreeViewAdapter;
import com.example.javademo.tree.TreeViewItemClickListener;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
/** 树中的元素集合 */
private ArrayList<Element> elements;
/** 数据源元素集合 */
private ArrayList<Element> elementsData;
private ListView treeView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
init();
treeView = findViewById(R.id.treeView);
TreeViewAdapter treeViewAdapter = new TreeViewAdapter(elements,elementsData,inflater);
TreeViewItemClickListener treeViewItemClickListener = new TreeViewItemClickListener(treeViewAdapter);
// 回调函数-没有子集item点击事件
treeViewItemClickListener.setNoHasChildrenItemClick(new TreeViewItemClickListener.TreeViewNoHasChildrenItemClick() {
@Override
public void onTreeItemClick(int position, Element element) {
System.out.println("element"+element.getContentText());
}
});
treeView.setAdapter(treeViewAdapter);
treeView.setOnItemClickListener(treeViewItemClickListener);
}
private void init(){
elements = new ArrayList<Element>();
elementsData = new ArrayList<Element>();
//添加节点 -- 节点名称,节点level,节点id,父节点id,是否有子节点,是否展开
//添加最外层节点
Element n1 = new Element("朝阳区", Element.TOP_LEVEL, 0, Element.NO_PARENT, true, false);
// 添加第一层节点
Element n11 = new Element("地铁2号线建设广场站", Element.TOP_LEVEL+1,11,n1.getId(),true,false);
// 添加第一层节点
Element n12 = new Element("地铁5号线湖西路站", Element.TOP_LEVEL+1,12,n1.getId(),true,false);
// 添加第一层节点
Element n13 = new Element("宽平大路北旧城改造地块", Element.TOP_LEVEL+1,13,n1.getId(),true,false);
//添加最外层节点
Element n2 = new Element("绿园区", Element.TOP_LEVEL, 1, Element.NO_PARENT, true, false);
// 添加第一层节点
Element n22 = new Element("合心镇加油站", Element.TOP_LEVEL+1,22,n2.getId(),true,false);
// 添加第一层节点
Element n23 = new Element("皓月5号地", Element.TOP_LEVEL+1,23,n2.getId(),true,false);
// 添加第一层节点
Element n24 = new Element("西安桥", Element.TOP_LEVEL+1,24,n2.getId(),true,false);
//添加初始树元素
elements.add(n1);
elements.add(n2);
// 创建数据源
elementsData.add(n11);
elementsData.add(n12);
elementsData.add(n13);
elementsData.add(n22);
elementsData.add(n23);
elementsData.add(n24);
}
}