3414
- 收藏
- 点赞
- 分享
- 举报
列表树实例
本帖最后由 Heguming 于 2015-11-9 17:48 编辑
最近,在弄一个电子书App,需要用到列表树结构,相信大家以后也会遇到,特此做下分享,高手请绕行~~~~~~
详细工程请查看附件,下面对其进行简要的分析:
先介绍下关键类吧:TreeElement,该类是列表树中的每个节点模型,代码如下:
[code]
package com.ccl.util.tree;
import java.util.ArrayList;
import android.view.View.OnClickListener;
public class TreeElement {
private String id;
private String value;
private String caption;
private int position = 0;
private int level = 0;
private boolean isHasChild;
private boolean isExpanded = false;
private boolean isLastTwig = false;
private TreeElement parent;
private ArrayList childList;
private ArrayList spaceList = new ArrayList();
private int img_tree_space_n = R.drawable.tree_space_n;
private int img_tree_space_y = R.drawable.tree_space_y;
private OnClickListener onClickListener;
public TreeElement() {
super();
}
public TreeElement(String id, String value, String caption,
Boolean isHasChild, OnClickListener onClickListener) {
this.id = id;
this.value = value;
this.caption = caption;
this.isHasChild = isHasChild;
if (isHasChild) {
this.childList = new ArrayList();
}
this.setCaptionOnClickListener(onClickListener);
}
public void setId(String id) {
this.id = id;
}
public void setValue(String value) {
this.value = value;
}
public void setCaption(String caption) {
this.caption = caption;
}
public void setPosition(int position) {
this.position = position;
}
public void setLevel(int level) {
this.level = level;
}
public void setIsHasChild(boolean isHasChild) {
this.isHasChild = isHasChild;
}
public void setIsExpanded(boolean isExpanded) {
this.isExpanded = isExpanded;
}
public void setIsLastTwig(boolean isLastTwig) {
this.isLastTwig = isLastTwig;
}
public void setParent(TreeElement parent) {
this.parent = parent;
}
public void setChildList(ArrayList childList) {
this.childList = childList;
}
public void setSpaceList(ArrayList spaceList) {
this.spaceList = spaceList;
}
public void setCaptionOnClickListener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
public String getId() {
return id;
}
public String getValue() {
return value;
}
public String getCaption() {
return caption;
}
public int getPosition() {
return position;
}
public int getLevel() {
return level;
}
public boolean getIsHasChild() {
return isHasChild;
}
public boolean getIsExpanded() {
return isExpanded;
}
public boolean getIsLastTwig() {
return isLastTwig;
}
public TreeElement getParent() {
return parent;
}
public ArrayList getChildList() {
return childList;
}
public ArrayList getSpaceList() {
return spaceList;
}
public OnClickListener getOnClickListener() {
return onClickListener;
}
public void addChild(TreeElement treeElement) {
TreeElement parent = this;
treeElement.parent = parent;
if (parent != null && childList != null && childList.size() > 0) {
TreeElement child = childList.get(childList.size() - 1);
child.setIsLastTwig(false);
childList.set(childList.size() - 1, child);
}
childList.add(treeElement);
parent.setIsHasChild(true);
parent.setChildList(childList);
treeElement.setLevel(this.level + 1);
treeElement.setIsLastTwig(true);
if (this.level > 0) {
treeElement.getSpaceList().addAll(spaceList);
if (isLastTwig) {
treeElement.getSpaceList().add(img_tree_space_n);
} else {
treeElement.getSpaceList().add(img_tree_space_y);
}
}
}
}
[/code]
该类主要包含了以下几个参数:
构造参数:
id---节点序列号,采用String类型,可以清楚地知道其所属关系,即该节点位于该列表树的第几层。
value--节点值,即该节点所包含的数据。
caption---节点标题,显示在屏幕中的节点标题信息。
isHasChild---该节点是否包含子节点。
onClickListener---事件监听器,通过该事件监听器,可以设置每次点击事件所需要的响应。
其他参数:
position---该节点在列表中的位置,包括展开树后的子节点在内。
level---该节点在树的第几层。
parent---该节点的父节点,同为TreeElement类型。
childList---该节点的子节点的集合。
spaceList---所有父节点连线图形的集合,如下图:
isExpanded---该节点是否处于展开状态,可根据此值,分别设置节点的图形标志,如下图:
isLastTwig---该节点是否为本层的最后一个节点,可根据此值,分别设置节点的连接标志,如下图:
连线图形、图形标志及连接标志在视图中的位置:
其中,属于该节点本身的固有的参数为:id、value、caption及onClickListener,这四个参数加上isHasChild,可直接在初始化列表树时直接赋值。
其余参数,包括isHasChild,isExpanded,isLastTwig,position,level,parent,childList,spaceList在内,属于该节点在该树中的关系属性,不可直接通过实例化该类赋值,需要在以下方法中分别赋值:
level、parent、childList、spaceList、isLastTwig---这些变量通过执行addChild(TreeElement treeElement)方法时赋值。
[code]
public void addChild(TreeElement treeElement) {
TreeElement parent = this;
treeElement.parent = parent;
if (parent != null && childList != null && childList.size() > 0) {
TreeElement child = childList.get(childList.size() - 1);
child.setIsLastTwig(false);
childList.set(childList.size() - 1, child);
}
childList.add(treeElement);
parent.setIsHasChild(true);
parent.setChildList(childList);
treeElement.setLevel(this.level + 1);
treeElement.setIsLastTwig(true);
if (this.level > 0) {
treeElement.getSpaceList().addAll(spaceList);
if (isLastTwig) {
treeElement.getSpaceList().add(img_tree_space_n);
} else {
treeElement.getSpaceList().add(img_tree_space_y);
}
}
}
[/code]
由该方法可以看出,当对某一个节点添加子节点时,首先将该子节点的父节点设置为当前节点parent,即对需要添加的子节点parent参数赋值。
然后,将当前父节点的最后一个子节点的IsLastTwig属性设置为false,将该子节点的IsLastTwig属性设置为true,即对isLastTwig参数赋值。
同时,将需要添加的子节点添加至当前父节点ChildList中,即对childList参数赋值,并再此将该父节点IsHasChild属性设置为true,即当前节点包含子节点。
最后,将需要添加的子节点的层级设置为当前父节点的层级+1(level + 1),即对level参数赋值,并根据level层级,将所有父节点的连线图形,并加上自身的连线图形,全部添加至spaceList,即对spaceList参数赋值。
isExpanded、position---当响应含有子节点的当前节点的点击事件时,这两个变量被赋值。通过对isExpanded变量进行赋值,进而改变父节点的展开/收缩状态(isExpanded为true时展开)。通过对position变量进行赋值,进而设置该节点在列表树中的位置。当isExpanded为false时,position的值为该节点在当前层级(level)中的位置。相反,当isExpanded的值为true时,position的值还需加上其子节点后,在所有层级(level)中的位置。对这两个变量赋值的方法在TreeViewAdapter中,代码如下:
[code]
package com.ccl.util.tree;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class TreeViewAdapter extends ArrayAdapter {
private int img_leaf = R.drawable.icon_user;// 没有子节点的节点图标
private int img_expand = R.drawable.outline_list_expand;// 展开的图标
private int img_collapse = R.drawable.outline_list_collapse;// 收缩的图标
private int img_tree_space_1 = R.drawable.tree_space_1;// 连线图形
private int img_tree_space_2 = R.drawable.tree_space_2;
private Context context;
private ArrayList treeElementList;
private int viewResourceId;
public TreeViewAdapter(Context context, int viewResourceId,
ArrayList treeElementList) {
super(context, viewResourceId, treeElementList);
this.context = context;
this.viewResourceId = viewResourceId;
this.treeElementList = treeElementList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
convertView = LayoutInflater.from(context)
.inflate(viewResourceId, null);
holder = new ViewHolder();
holder.caption = (TextView) convertView.findViewById(R.id.caption);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.space = (LinearLayout) convertView.findViewById(R.id.space);
convertView.setTag(holder);
TreeElement treeElement = treeElementList.get(position);
int level = treeElement.getLevel();
if (level == 0) {// 根节点
} else {
ArrayList spaceList = treeElement.getSpaceList();
// 绘制前面的组织架构线条
for (int i = 0; i < spaceList.size(); i++) {
ImageView img = new ImageView(context);
img.setImageResource(spaceList.get(i));
holder.space.addView(img);
}
ImageView img = new ImageView(context);
// 节点图标
if (treeElement.getIsLastTwig()) {
img.setImageResource(img_tree_space_2);
} else {
img.setImageResource(img_tree_space_1);
}
holder.space.addView(img);
}
if (treeElement.getIsHasChild()) {
if (treeElement.getIsExpanded()) {
holder.icon.setImageResource(img_expand);
} else {
holder.icon.setImageResource(img_collapse);
}
holder.icon.setOnClickListener(new TreeElementIconClickListener(
context, treeElementList, this, treeElement.getPosition()));
} else {
holder.icon.setImageResource(img_leaf);
}
holder.caption.setText(treeElement.getCaption()); // 设置标题
if (treeElement.getOnClickListener() != null) { // 设置文字的点击事件
holder.caption.setTag(treeElement.getValue());
holder.caption.setOnClickListener(treeElement.getOnClickListener());
}
return convertView;
}
class ViewHolder {
LinearLayout space;
TextView caption;
ImageView icon;
}
public static class TreeElementIconClickListener implements OnClickListener {
private Context context;
private ArrayList treeElementList;
private TreeViewAdapter treeViewAdapter;
private int position;
public TreeElementIconClickListener(Context mContext,
ArrayList treeElementList,
TreeViewAdapter treeViewAdapter, int position) {
this.context = mContext;
this.treeElementList = treeElementList;
this.treeViewAdapter = treeViewAdapter;
this.position = position;
}
@Override
public void onClick(View v) {
if (!treeElementList.get(position).getIsHasChild()) {
Toast.makeText(context,
treeElementList.get(position).getCaption(),
Toast.LENGTH_SHORT).show();
return;
}
if (treeElementList.get(position).getIsExpanded()) {
treeElementList.get(position).setIsExpanded(false);
TreeElement treeElement = treeElementList.get(position);
ArrayList tempList = new ArrayList();
for (int i = position + 1; i < treeElementList.size(); i++) {
if (treeElement.getLevel() >= treeElementList.get(i)
.getLevel()) {
break;
}
tempList.add(treeElementList.get(i));
}
treeElementList.removeAll(tempList);
for (int i = position + 1; i < treeElementList.size(); i++) {
treeElementList.get(i).setPosition(i);
}
treeViewAdapter.notifyDataSetChanged();
} else {
TreeElement treeElement = treeElementList.get(position);
treeElement.setIsExpanded(true);
int level = treeElement.getLevel();
ArrayList tempList = treeElement.getChildList();
for (int i = 0; i < tempList.size(); i++) {
TreeElement element = tempList.get(i);
element.setLevel(level + 1);
element.setIsExpanded(false);
treeElementList.add(position + i + 1, element);
}
for (int i = position + 1; i < treeElementList.size(); i++) {
treeElementList.get(i).setPosition(i);
}
treeViewAdapter.notifyDataSetChanged();
}
}
}
}
[/code]
在getView(int position, View convertView, ViewGroup parent)方法中,先获取当前节点treeElement,然后根据treeElement层级level是否为0(即是否为根节点)进行分别处理。
当level不为0时,获取spaceList所有父节点的连线图形,通过addView(View view)方法,将所有连线图形添加至列表item相应View中。
同时,通过获取节点treeElement的IsLastTwig属性,判断当前节点是否为相同层级下的最后一个节点,并根据此判断,分别向列表item相应View中添加不同的连接标志。
相反,当level等于0时,即当前节点为根节点时,以上图形无须添加。
接着,判断当前节点有无子节点。如果含有,则获取节点IsExpanded属性,并根据该属性的值,设置不同的图形标志。同时,为当前节点的图形标志设置onClick监听器。
如果不含有,则直接将当前节点的图形标志设为终节点即可(即不包含子节点的节点)。
最后,为当前节点设置标题caption及值value,标题通过setText()方法显示在TextView上,值则通过setTag()方法存储在TextView中。
另外地,需要特意说明一下图形标志的点击事件,即TreeElementIconClickListener类。
该类主要实现了onClick(View view)方法,在该方法内部,主要做了以下几件事:
1.判断当前点击节点的展开/收缩状态。
2.若该节点为展开状态,响应点击事件后,设置该节点为收缩状态:treeElementList.get(position).setIsExpanded(false)。然后将该节点内的所有子节点添加至新的TreeElement集合tempList中,通过该集合对treeElementList进行定向删除:treeElementList.removeAll(tempList)。最后,更新列表position及整个列表:treeViewAdapter.notifyDataSetChanged()。
3.若该节点为收缩状态,响应点击事件后,设置该节点为展开状态:treeElement.setIsExpanded(true),然后通过treeElement获取当前层级level及当前节点的子节点集合:tempList,并将该集合添加至treeElementList中,同时设置子节点的相关属性:element.setLevel(level + 1)、element.setIsExpand(false)。最后,更新列表position及整列表:
treeViewAdapter.notifyDataSetChanged()。
最后,是MainActivity代码,主要功能是初始化树,向其中添加节点,并更新列表。
[code]
package com.ccl.util.tree;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
private ListView lv_tree;
private TreeViewAdapter treeViewAdapter;
private ArrayList rootList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv_tree = (ListView) findViewById(R.id.lv_tree);
rootList = new ArrayList();
treeViewAdapter = new TreeViewAdapter(this, R.layout.atom_tree,
rootList);
lv_tree.setAdapter(treeViewAdapter);
OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "value:" + v.getTag(),
Toast.LENGTH_LONG).show();
}
};
initTree(onClickListener);
treeViewAdapter.notifyDataSetChanged();
// TreeElementIconClickListener treeElementIconClickListener = new
// TreeElementIconClickListener(
// MainActivity.this, mRootList, treeViewAdapter, 0);
// treeElementIconClickListener.onClick(null);
}
private void initTree(OnClickListener onClickListener) {
// TODO Auto-generated method stub
TreeElement rootElement = new TreeElement("0", "根结点", "根节点", true,
onClickListener);
TreeElement treeElement1 = new TreeElement("1", "节点1", "节点1", true,
onClickListener);
TreeElement treeElement2 = new TreeElement("2", "节点2", "节点2", false,
onClickListener);
TreeElement treeElement3 = new TreeElement("3", "节点3", "节点3", false,
onClickListener);
TreeElement treeElement4 = new TreeElement("4", "节点4", "节点4", true,
onClickListener);
rootElement.addChild(treeElement1);
rootElement.addChild(treeElement2);
rootElement.addChild(treeElement3);
rootElement.addChild(treeElement4);
TreeElement treeElement1_1 = new TreeElement("1_1", "节点1_1", "节点1_1",
true, onClickListener);
TreeElement treeElement1_2 = new TreeElement("1_2", "节点1_2", "节点1_2",
false, onClickListener);
TreeElement treeElement1_3 = new TreeElement("1_3", "节点1_3", "节点1_3",
true, onClickListener);
treeElement1.addChild(treeElement1_1);
treeElement1.addChild(treeElement1_2);
treeElement1.addChild(treeElement1_3);
TreeElement treeElement4_1 = new TreeElement("4_1", "节点4_1", "节点4_1",
true, onClickListener);
TreeElement treeElement4_2 = new TreeElement("4_2", "节点4_2", "节点4_2",
false, onClickListener);
TreeElement treeElement4_3 = new TreeElement("4_3", "节点4_3", "节点4_3",
true, onClickListener);
treeElement4.addChild(treeElement4_1);
treeElement4.addChild(treeElement4_2);
treeElement4.addChild(treeElement4_3);
TreeElement treeElement1_1_1 = new TreeElement("1_1_1", "节点1_1_1",
"节点1_1_1", false, onClickListener);
treeElement1_1.addChild(treeElement1_1_1);
TreeElement treeElement1_3_1 = new TreeElement("1_3_1", "节点1_3_1",
"节点1_3_1", true, onClickListener);
TreeElement treeElement1_3_2 = new TreeElement("1_3_2", "节点1_3_2",
"节点1_3_2", false, onClickListener);
treeElement1_3.addChild(treeElement1_3_1);
treeElement1_3.addChild(treeElement1_3_2);
TreeElement treeElement4_1_1 = new TreeElement("4_1_1", "节点4_1_1",
"节点4_1_1", false, onClickListener);
TreeElement treeElement4_3_1 = new TreeElement("4_3_1", "节点4_3_1",
"节点4_3_1", false, onClickListener);
treeElement4_1.addChild(treeElement4_1_1);
treeElement4_3.addChild(treeElement4_3_1);
TreeElement treeElement1_3_1_1 = new TreeElement("1_3_1_1",
"节点1_3_1_1", "节点1_3_1_1", false, onClickListener);
treeElement1_3_1.addChild(treeElement1_3_1_1);
rootList.add(rootElement);
}
}
[/code]
其中,注释部分代码的功能为展开根节点,用户可根据需要自行添加。
好了,以上代码分析完毕,谢谢!
原创,转载请注明出处 :)
附件:tree.rar
最近,在弄一个电子书App,需要用到列表树结构,相信大家以后也会遇到,特此做下分享,高手请绕行~~~~~~
详细工程请查看附件,下面对其进行简要的分析:
先介绍下关键类吧:TreeElement,该类是列表树中的每个节点模型,代码如下:
[code]
package com.ccl.util.tree;
import java.util.ArrayList;
import android.view.View.OnClickListener;
public class TreeElement {
private String id;
private String value;
private String caption;
private int position = 0;
private int level = 0;
private boolean isHasChild;
private boolean isExpanded = false;
private boolean isLastTwig = false;
private TreeElement parent;
private ArrayList
private ArrayList
private int img_tree_space_n = R.drawable.tree_space_n;
private int img_tree_space_y = R.drawable.tree_space_y;
private OnClickListener onClickListener;
public TreeElement() {
super();
}
public TreeElement(String id, String value, String caption,
Boolean isHasChild, OnClickListener onClickListener) {
this.id = id;
this.value = value;
this.caption = caption;
this.isHasChild = isHasChild;
if (isHasChild) {
this.childList = new ArrayList
}
this.setCaptionOnClickListener(onClickListener);
}
public void setId(String id) {
this.id = id;
}
public void setValue(String value) {
this.value = value;
}
public void setCaption(String caption) {
this.caption = caption;
}
public void setPosition(int position) {
this.position = position;
}
public void setLevel(int level) {
this.level = level;
}
public void setIsHasChild(boolean isHasChild) {
this.isHasChild = isHasChild;
}
public void setIsExpanded(boolean isExpanded) {
this.isExpanded = isExpanded;
}
public void setIsLastTwig(boolean isLastTwig) {
this.isLastTwig = isLastTwig;
}
public void setParent(TreeElement parent) {
this.parent = parent;
}
public void setChildList(ArrayList
this.childList = childList;
}
public void setSpaceList(ArrayList
this.spaceList = spaceList;
}
public void setCaptionOnClickListener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
public String getId() {
return id;
}
public String getValue() {
return value;
}
public String getCaption() {
return caption;
}
public int getPosition() {
return position;
}
public int getLevel() {
return level;
}
public boolean getIsHasChild() {
return isHasChild;
}
public boolean getIsExpanded() {
return isExpanded;
}
public boolean getIsLastTwig() {
return isLastTwig;
}
public TreeElement getParent() {
return parent;
}
public ArrayList
return childList;
}
public ArrayList
return spaceList;
}
public OnClickListener getOnClickListener() {
return onClickListener;
}
public void addChild(TreeElement treeElement) {
TreeElement parent = this;
treeElement.parent = parent;
if (parent != null && childList != null && childList.size() > 0) {
TreeElement child = childList.get(childList.size() - 1);
child.setIsLastTwig(false);
childList.set(childList.size() - 1, child);
}
childList.add(treeElement);
parent.setIsHasChild(true);
parent.setChildList(childList);
treeElement.setLevel(this.level + 1);
treeElement.setIsLastTwig(true);
if (this.level > 0) {
treeElement.getSpaceList().addAll(spaceList);
if (isLastTwig) {
treeElement.getSpaceList().add(img_tree_space_n);
} else {
treeElement.getSpaceList().add(img_tree_space_y);
}
}
}
}
[/code]
该类主要包含了以下几个参数:
构造参数:
id---节点序列号,采用String类型,可以清楚地知道其所属关系,即该节点位于该列表树的第几层。
value--节点值,即该节点所包含的数据。
caption---节点标题,显示在屏幕中的节点标题信息。
isHasChild---该节点是否包含子节点。
onClickListener---事件监听器,通过该事件监听器,可以设置每次点击事件所需要的响应。
其他参数:
position---该节点在列表中的位置,包括展开树后的子节点在内。
level---该节点在树的第几层。
parent---该节点的父节点,同为TreeElement类型。
childList---该节点的子节点的集合。
spaceList---所有父节点连线图形的集合,如下图:
isExpanded---该节点是否处于展开状态,可根据此值,分别设置节点的图形标志,如下图:
isLastTwig---该节点是否为本层的最后一个节点,可根据此值,分别设置节点的连接标志,如下图:
连线图形、图形标志及连接标志在视图中的位置:
其中,属于该节点本身的固有的参数为:id、value、caption及onClickListener,这四个参数加上isHasChild,可直接在初始化列表树时直接赋值。
其余参数,包括isHasChild,isExpanded,isLastTwig,position,level,parent,childList,spaceList在内,属于该节点在该树中的关系属性,不可直接通过实例化该类赋值,需要在以下方法中分别赋值:
level、parent、childList、spaceList、isLastTwig---这些变量通过执行addChild(TreeElement treeElement)方法时赋值。
[code]
public void addChild(TreeElement treeElement) {
TreeElement parent = this;
treeElement.parent = parent;
if (parent != null && childList != null && childList.size() > 0) {
TreeElement child = childList.get(childList.size() - 1);
child.setIsLastTwig(false);
childList.set(childList.size() - 1, child);
}
childList.add(treeElement);
parent.setIsHasChild(true);
parent.setChildList(childList);
treeElement.setLevel(this.level + 1);
treeElement.setIsLastTwig(true);
if (this.level > 0) {
treeElement.getSpaceList().addAll(spaceList);
if (isLastTwig) {
treeElement.getSpaceList().add(img_tree_space_n);
} else {
treeElement.getSpaceList().add(img_tree_space_y);
}
}
}
[/code]
由该方法可以看出,当对某一个节点添加子节点时,首先将该子节点的父节点设置为当前节点parent,即对需要添加的子节点parent参数赋值。
然后,将当前父节点的最后一个子节点的IsLastTwig属性设置为false,将该子节点的IsLastTwig属性设置为true,即对isLastTwig参数赋值。
同时,将需要添加的子节点添加至当前父节点ChildList中,即对childList参数赋值,并再此将该父节点IsHasChild属性设置为true,即当前节点包含子节点。
最后,将需要添加的子节点的层级设置为当前父节点的层级+1(level + 1),即对level参数赋值,并根据level层级,将所有父节点的连线图形,并加上自身的连线图形,全部添加至spaceList,即对spaceList参数赋值。
isExpanded、position---当响应含有子节点的当前节点的点击事件时,这两个变量被赋值。通过对isExpanded变量进行赋值,进而改变父节点的展开/收缩状态(isExpanded为true时展开)。通过对position变量进行赋值,进而设置该节点在列表树中的位置。当isExpanded为false时,position的值为该节点在当前层级(level)中的位置。相反,当isExpanded的值为true时,position的值还需加上其子节点后,在所有层级(level)中的位置。对这两个变量赋值的方法在TreeViewAdapter中,代码如下:
[code]
package com.ccl.util.tree;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class TreeViewAdapter extends ArrayAdapter
private int img_leaf = R.drawable.icon_user;// 没有子节点的节点图标
private int img_expand = R.drawable.outline_list_expand;// 展开的图标
private int img_collapse = R.drawable.outline_list_collapse;// 收缩的图标
private int img_tree_space_1 = R.drawable.tree_space_1;// 连线图形
private int img_tree_space_2 = R.drawable.tree_space_2;
private Context context;
private ArrayList
private int viewResourceId;
public TreeViewAdapter(Context context, int viewResourceId,
ArrayList
super(context, viewResourceId, treeElementList);
this.context = context;
this.viewResourceId = viewResourceId;
this.treeElementList = treeElementList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
convertView = LayoutInflater.from(context)
.inflate(viewResourceId, null);
holder = new ViewHolder();
holder.caption = (TextView) convertView.findViewById(R.id.caption);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.space = (LinearLayout) convertView.findViewById(R.id.space);
convertView.setTag(holder);
TreeElement treeElement = treeElementList.get(position);
int level = treeElement.getLevel();
if (level == 0) {// 根节点
} else {
ArrayList
// 绘制前面的组织架构线条
for (int i = 0; i < spaceList.size(); i++) {
ImageView img = new ImageView(context);
img.setImageResource(spaceList.get(i));
holder.space.addView(img);
}
ImageView img = new ImageView(context);
// 节点图标
if (treeElement.getIsLastTwig()) {
img.setImageResource(img_tree_space_2);
} else {
img.setImageResource(img_tree_space_1);
}
holder.space.addView(img);
}
if (treeElement.getIsHasChild()) {
if (treeElement.getIsExpanded()) {
holder.icon.setImageResource(img_expand);
} else {
holder.icon.setImageResource(img_collapse);
}
holder.icon.setOnClickListener(new TreeElementIconClickListener(
context, treeElementList, this, treeElement.getPosition()));
} else {
holder.icon.setImageResource(img_leaf);
}
holder.caption.setText(treeElement.getCaption()); // 设置标题
if (treeElement.getOnClickListener() != null) { // 设置文字的点击事件
holder.caption.setTag(treeElement.getValue());
holder.caption.setOnClickListener(treeElement.getOnClickListener());
}
return convertView;
}
class ViewHolder {
LinearLayout space;
TextView caption;
ImageView icon;
}
public static class TreeElementIconClickListener implements OnClickListener {
private Context context;
private ArrayList
private TreeViewAdapter treeViewAdapter;
private int position;
public TreeElementIconClickListener(Context mContext,
ArrayList
TreeViewAdapter treeViewAdapter, int position) {
this.context = mContext;
this.treeElementList = treeElementList;
this.treeViewAdapter = treeViewAdapter;
this.position = position;
}
@Override
public void onClick(View v) {
if (!treeElementList.get(position).getIsHasChild()) {
Toast.makeText(context,
treeElementList.get(position).getCaption(),
Toast.LENGTH_SHORT).show();
return;
}
if (treeElementList.get(position).getIsExpanded()) {
treeElementList.get(position).setIsExpanded(false);
TreeElement treeElement = treeElementList.get(position);
ArrayList
for (int i = position + 1; i < treeElementList.size(); i++) {
if (treeElement.getLevel() >= treeElementList.get(i)
.getLevel()) {
break;
}
tempList.add(treeElementList.get(i));
}
treeElementList.removeAll(tempList);
for (int i = position + 1; i < treeElementList.size(); i++) {
treeElementList.get(i).setPosition(i);
}
treeViewAdapter.notifyDataSetChanged();
} else {
TreeElement treeElement = treeElementList.get(position);
treeElement.setIsExpanded(true);
int level = treeElement.getLevel();
ArrayList
for (int i = 0; i < tempList.size(); i++) {
TreeElement element = tempList.get(i);
element.setLevel(level + 1);
element.setIsExpanded(false);
treeElementList.add(position + i + 1, element);
}
for (int i = position + 1; i < treeElementList.size(); i++) {
treeElementList.get(i).setPosition(i);
}
treeViewAdapter.notifyDataSetChanged();
}
}
}
}
[/code]
在getView(int position, View convertView, ViewGroup parent)方法中,先获取当前节点treeElement,然后根据treeElement层级level是否为0(即是否为根节点)进行分别处理。
当level不为0时,获取spaceList所有父节点的连线图形,通过addView(View view)方法,将所有连线图形添加至列表item相应View中。
同时,通过获取节点treeElement的IsLastTwig属性,判断当前节点是否为相同层级下的最后一个节点,并根据此判断,分别向列表item相应View中添加不同的连接标志。
相反,当level等于0时,即当前节点为根节点时,以上图形无须添加。
接着,判断当前节点有无子节点。如果含有,则获取节点IsExpanded属性,并根据该属性的值,设置不同的图形标志。同时,为当前节点的图形标志设置onClick监听器。
如果不含有,则直接将当前节点的图形标志设为终节点即可(即不包含子节点的节点)。
最后,为当前节点设置标题caption及值value,标题通过setText()方法显示在TextView上,值则通过setTag()方法存储在TextView中。
另外地,需要特意说明一下图形标志的点击事件,即TreeElementIconClickListener类。
该类主要实现了onClick(View view)方法,在该方法内部,主要做了以下几件事:
1.判断当前点击节点的展开/收缩状态。
2.若该节点为展开状态,响应点击事件后,设置该节点为收缩状态:treeElementList.get(position).setIsExpanded(false)。然后将该节点内的所有子节点添加至新的TreeElement集合tempList中,通过该集合对treeElementList进行定向删除:treeElementList.removeAll(tempList)。最后,更新列表position及整个列表:treeViewAdapter.notifyDataSetChanged()。
3.若该节点为收缩状态,响应点击事件后,设置该节点为展开状态:treeElement.setIsExpanded(true),然后通过treeElement获取当前层级level及当前节点的子节点集合:tempList,并将该集合添加至treeElementList中,同时设置子节点的相关属性:element.setLevel(level + 1)、element.setIsExpand(false)。最后,更新列表position及整列表:
treeViewAdapter.notifyDataSetChanged()。
最后,是MainActivity代码,主要功能是初始化树,向其中添加节点,并更新列表。
[code]
package com.ccl.util.tree;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
private ListView lv_tree;
private TreeViewAdapter treeViewAdapter;
private ArrayList
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv_tree = (ListView) findViewById(R.id.lv_tree);
rootList = new ArrayList
treeViewAdapter = new TreeViewAdapter(this, R.layout.atom_tree,
rootList);
lv_tree.setAdapter(treeViewAdapter);
OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "value:" + v.getTag(),
Toast.LENGTH_LONG).show();
}
};
initTree(onClickListener);
treeViewAdapter.notifyDataSetChanged();
// TreeElementIconClickListener treeElementIconClickListener = new
// TreeElementIconClickListener(
// MainActivity.this, mRootList, treeViewAdapter, 0);
// treeElementIconClickListener.onClick(null);
}
private void initTree(OnClickListener onClickListener) {
// TODO Auto-generated method stub
TreeElement rootElement = new TreeElement("0", "根结点", "根节点", true,
onClickListener);
TreeElement treeElement1 = new TreeElement("1", "节点1", "节点1", true,
onClickListener);
TreeElement treeElement2 = new TreeElement("2", "节点2", "节点2", false,
onClickListener);
TreeElement treeElement3 = new TreeElement("3", "节点3", "节点3", false,
onClickListener);
TreeElement treeElement4 = new TreeElement("4", "节点4", "节点4", true,
onClickListener);
rootElement.addChild(treeElement1);
rootElement.addChild(treeElement2);
rootElement.addChild(treeElement3);
rootElement.addChild(treeElement4);
TreeElement treeElement1_1 = new TreeElement("1_1", "节点1_1", "节点1_1",
true, onClickListener);
TreeElement treeElement1_2 = new TreeElement("1_2", "节点1_2", "节点1_2",
false, onClickListener);
TreeElement treeElement1_3 = new TreeElement("1_3", "节点1_3", "节点1_3",
true, onClickListener);
treeElement1.addChild(treeElement1_1);
treeElement1.addChild(treeElement1_2);
treeElement1.addChild(treeElement1_3);
TreeElement treeElement4_1 = new TreeElement("4_1", "节点4_1", "节点4_1",
true, onClickListener);
TreeElement treeElement4_2 = new TreeElement("4_2", "节点4_2", "节点4_2",
false, onClickListener);
TreeElement treeElement4_3 = new TreeElement("4_3", "节点4_3", "节点4_3",
true, onClickListener);
treeElement4.addChild(treeElement4_1);
treeElement4.addChild(treeElement4_2);
treeElement4.addChild(treeElement4_3);
TreeElement treeElement1_1_1 = new TreeElement("1_1_1", "节点1_1_1",
"节点1_1_1", false, onClickListener);
treeElement1_1.addChild(treeElement1_1_1);
TreeElement treeElement1_3_1 = new TreeElement("1_3_1", "节点1_3_1",
"节点1_3_1", true, onClickListener);
TreeElement treeElement1_3_2 = new TreeElement("1_3_2", "节点1_3_2",
"节点1_3_2", false, onClickListener);
treeElement1_3.addChild(treeElement1_3_1);
treeElement1_3.addChild(treeElement1_3_2);
TreeElement treeElement4_1_1 = new TreeElement("4_1_1", "节点4_1_1",
"节点4_1_1", false, onClickListener);
TreeElement treeElement4_3_1 = new TreeElement("4_3_1", "节点4_3_1",
"节点4_3_1", false, onClickListener);
treeElement4_1.addChild(treeElement4_1_1);
treeElement4_3.addChild(treeElement4_3_1);
TreeElement treeElement1_3_1_1 = new TreeElement("1_3_1_1",
"节点1_3_1_1", "节点1_3_1_1", false, onClickListener);
treeElement1_3_1.addChild(treeElement1_3_1_1);
rootList.add(rootElement);
}
}
[/code]
其中,注释部分代码的功能为展开根节点,用户可根据需要自行添加。
好了,以上代码分析完毕,谢谢!
原创,转载请注明出处 :)
附件:tree.rar
文件: tree.rar
下载
我来回答
回答2个
时间排序
认可量排序
认可0
认可0
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
相关问答
-
2008-08-01 19:16:42
-
12013-11-21 21:32:49
-
2016-03-08 15:08:31
-
2008-07-31 01:02:40
-
2013-01-04 20:09:43
-
2012-12-04 13:42:23
-
2015-11-06 14:22:10
-
2013-11-20 13:54:20
-
2019-01-17 10:56:04
-
2018-12-12 10:25:24
-
2023-10-26 15:50:22
-
2018-12-06 17:43:02
-
2020-07-31 17:16:33
-
2021-01-13 16:49:22
-
2021-01-14 13:43:23
-
2018-12-18 14:24:48
-
2008-07-15 18:04:26
-
2015-11-03 19:03:43
-
2018-12-07 16:36:51
无更多相似问答 去提问
点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
悬赏问答
-
5Hi3516CV610 如何使用SD卡升级固件
-
5cat /dev/logmpp 报错 <3>[ vi] [func]:vi_send_frame_node [line]:99 [info]:vi pic queue is full!
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
-
10EB-RV1126-BC-191板子运行自己编码的程序
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认