TreeView
准备
Node
package function.tree;
import com.fr.android.platform.data.bean.IFEntryNode;
import java.util.ArrayList;
import java.util.List;
/**
* @decs: Node
* @date: 2018/9/7 11:20
* @version: v 1.0
*/
public class Node<T> {
private IFEntryNode ifEntryNode;
private long id;
/**
* 根节点parentId为0
*/
private long parentId = 0;
private String name;
private T item;
/**
* 展否
*/
private boolean isExpand = false;
private int icon;
/**
* 下级子Node
*/
private List<Node<T>> children = new ArrayList<>();
/**
* 父Node
*/
private Node parent;
private int resourceId;
public IFEntryNode getIfEntryNode() {
return ifEntryNode;
}
public void setIfEntryNode(IFEntryNode ifEntryNode) {
this.ifEntryNode = ifEntryNode;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getParentId() {
return parentId;
}
public void setParentId(long parentId) {
this.parentId = parentId;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isExpand() {
return isExpand;
}
public List<Node<T>> getChildren() {
return children;
}
public void setChildren(List<Node<T>> children) {
this.children = children;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public int getResourceId() {
return resourceId;
}
public void setResourceId(int resourceId) {
this.resourceId = resourceId;
}
/**
* 根节点否
*/
public boolean isRoot() {
return parent == null;
}
/**
* 父节点展否
*/
public boolean isParentExpand() {
return parent != null && parent.isExpand();
}
/**
* 叶子节点否
*/
public boolean isLeaf() {
return children.size() == 0;
}
/**
* level
*/
public int getLevel() {
return parent == null ? 0 : parent.getLevel() + 1;
}
/**
* 展
*/
public void setExpand(boolean isExpand) {
this.isExpand = isExpand;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Node<?> node = (Node<?>) o;
return id == node.id &&
parentId == node.parentId &&
isExpand == node.isExpand &&
icon == node.icon &&
resourceId == node.resourceId &&
(name != null ? name.equals(node.name) : node.name == null) &&
(item != null ? item.equals(node.item) : node.item == null) &&
(children != null ? children.equals(node.children) : node.children == null) &&
(parent != null ? parent.equals(node.parent) : node.parent == null);
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (int) (parentId ^ (parentId >>> 32));
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (item != null ? item.hashCode() : 0);
result = 31 * result + (isExpand ? 1 : 0);
result = 31 * result + icon;
result = 31 * result + (children != null ? children.hashCode() : 0);
result = 31 * result + (parent != null ? parent.hashCode() : 0);
result = 31 * result + resourceId;
return result;
}
}
Tree
package function.tree;
import com.fr.android.platform.data.bean.IFEntryNode;
/**
* @decs: Tree
* @date: 2018/9/7 11:23
* @version: v 1.0
*/
public interface Tree {
/**
* IFEntryNode
*
* @return IFEntryNode
*/
IFEntryNode getIfEntryNode();
/**
* ID
*
* @return ID
*/
long getId();
/**
* 父ID
*
* @return ID
*/
long getParentId();
/**
* 名称
*
* @return 名称
*/
String getName();
/**
* 图ID
*
* @return 图ID
*/
int getImageResourceId();
}
TreeAdapter
package function.tree;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.self.zsp.dfs.R;
import java.util.List;
import butterknife.ButterKnife;
import util.DensityUtils;
/**
* @decs: 多层级树目录(适用RecyclerView)
* @date: 2018/9/7 11:24
* @version: v 1.0
*/
public class TreeAdapter<T extends Tree> extends RecyclerView.Adapter<TreeAdapter.TreeViewHolder> {
private static final float PADDING = 48;
private Context mContext;
private List<Node<T>> nodes;
private TreeItemClickListener treeItemClickListener;
/**
* constructor
*
* @param context 上下文
* @param data 数据
*/
public TreeAdapter(Context context, List<T> data) {
mContext = context;
setNodes(data);
}
/**
* 需传数据才刷TreeView(默根节点外节点都折)
*/
private void setNodes(List<T> data) {
List<Node<T>> allNodes = TreeHelper.getSortedNode(data, 0);
nodes = TreeHelper.filterVisibleNode(allNodes);
}
public void setListener(TreeItemClickListener mListener) {
this.treeItemClickListener = mListener;
}
/**
* 指定下标节点源数据
*
* @param index 指定下标
*/
public T getItem(int index) {
return nodes.get(index).getItem();
}
/**
* 指定id源数据
*
* @param id 指定id
*/
public T getItemById(int id) {
for (Node<T> node : nodes) {
if (node.getId() == id) {
return node.getItem();
}
}
return null;
}
/**
* 添子节点至指定id节点下(强挂数据于指定节点下)
* 子节点实际父节点并非指定节点则下次调{@link #setNodes(List)}时重调
*
* @param index 添数据至该下标节点处
* @param data 所添数据
*/
private void addChildrenByIndex(int index, List<T> data) {
Node<T> parent = nodes.get(index);
List<Node<T>> childNodes = TreeHelper.getSortedNode(data, 0);
List<Node<T>> children = parent.getChildren();
parent.setExpand(true);
for (Node<T> node : childNodes) {
node.setParent(parent);
children.add(node);
}
// 展节点
int count = addChildNodes(parent, index + 1);
notifyItemChanged(index);
notifyItemRangeInserted(index + 1, count);
}
/**
* 添子节点至指定id节点下(强挂数据于指定节点下)
* 子节点实际父节点并非指定节点则下次调{@link #setNodes(List)}时重调
*
* @param id 父节点id
* @param data 所添数据
*/
public void addChildrenById(int id, List<T> data) {
int index = findNode(id);
if (index != -1) {
addChildrenByIndex(index, data);
}
}
/**
* 据id查指定节点
*
* @param id 所查节点id
* @return 查找成功的下标(不存返-1)
*/
private int findNode(int id) {
int size = nodes.size();
for (int i = 0; i < size; i++) {
Node node = nodes.get(i);
if (node.getId() == id) {
return i;
}
}
return -1;
}
@NonNull
@Override
public TreeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.tree_item, parent, false);
return new TreeViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull TreeAdapter.TreeViewHolder holder, int position) {
Node node = nodes.get(position);
holder.setControl(node);
}
@Override
public int getItemCount() {
return nodes.size();
}
class TreeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView ivLeft;
private TextView tvName;
private ImageView ivRight;
private TreeViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
ivLeft = itemView.findViewById(R.id.ivTreeItemLeft);
tvName = itemView.findViewById(R.id.tvTreeItemName);
ivRight = itemView.findViewById(R.id.ivTreeItemRight);
itemView.setOnClickListener(this);
ivRight.setOnClickListener(this);
itemView.setTag(System.currentTimeMillis());
}
private void setControl(Node node) {
tvName.setText(node.getName());
tvName.setPadding(node.getLevel() * DensityUtils.pxToDp(mContext, PADDING), 0, 0, 0);
ivRight.setImageResource(node.getResourceId());
if (node.isLeaf()) {
ivLeft.setImageResource(0);
return;
}
int rotateDegree = node.isExpand() ? 90 : 0;
ivLeft.setRotation(0);
ivLeft.setRotation(rotateDegree);
ivLeft.setImageResource(R.drawable.arrow_right);
}
@Override
public void onClick(View view) {
Node<T> node = nodes.get(getLayoutPosition());
if (view.getId() == R.id.ivTreeItemRight) {
if (treeItemClickListener != null) {
treeItemClickListener.onRightClick(node);
}
return;
}
if (node != null) {
if (node.isLeaf()) {
if (treeItemClickListener != null) {
// Method getTag which get data.
treeItemClickListener.onClick(view, node);
}
} else {
long lastClickTime = (long) itemView.getTag();
// 避快点
if (System.currentTimeMillis() - lastClickTime < 200) {
return;
}
itemView.setTag(System.currentTimeMillis());
int rotateDegree = node.isExpand() ? -90 : 90;
ivLeft.animate().setDuration(100).rotationBy(rotateDegree).start();
boolean isExpand = node.isExpand();
node.setExpand(!isExpand);
if (!isExpand) {
notifyItemRangeInserted(getLayoutPosition() + 1, addChildNodes(node, getLayoutPosition() + 1));
} else {
notifyItemRangeRemoved(getLayoutPosition() + 1, removeChildNodes(node));
}
}
}
}
}
private int addChildNodes(Node<T> n, int startIndex) {
List<Node<T>> childList = n.getChildren();
int addChildCount = 0;
for (Node<T> node : childList) {
nodes.add(startIndex + addChildCount++, node);
// 递归展其下需展子元素
if (node.isExpand()) {
addChildCount += addChildNodes(node, startIndex + addChildCount);
}
}
return addChildCount;
}
/**
* 折父节点时删其下全子元素
*
* @param n node
* @return int
*/
private int removeChildNodes(Node<T> n) {
if (n.isLeaf()) {
return 0;
}
List<Node<T>> childList = n.getChildren();
int removeChildCount = childList.size();
nodes.removeAll(childList);
for (Node<T> node : childList) {
if (node.isExpand()) {
removeChildCount += removeChildNodes(node);
}
}
return removeChildCount;
}
}
TreeHelper
package function.tree;
import java.util.ArrayList;
import java.util.List;
/**
* @decs: TreeHelper
* @date: 2018/9/7 15:38
* @version: v 1.0
*/
public class TreeHelper {
/**
* 传需显数据(转为排序后Node数组)
*
* @param data 数据model需继{@link Tree}
* @param defaultExpandLevel 默展层级
* @return node数组
*/
public static <T extends Tree> List<Node<T>> getSortedNode(List<T> data, int defaultExpandLevel) {
List<Node<T>> result = new ArrayList<>();
// 转用户数据为List<Node>及设Node间关系(父子)
List<Node<T>> nodes = convertData2Node(data);
// 根节点
List<Node<T>> rootNodes = getRootNodes(nodes);
// 排序
for (Node<T> node : rootNodes) {
addNode(result, node, defaultExpandLevel, 1);
}
return result;
}
/**
* 过滤出全可见Node
*/
public static <T extends Tree> List<Node<T>> filterVisibleNode(List<Node<T>> nodes) {
List<Node<T>> result = new ArrayList<>();
for (Node<T> node : nodes) {
// 根节点或上层目录展状
if (node.isRoot() || node.isParentExpand()) {
result.add(node);
}
}
return result;
}
private static <T extends Tree> List<Node<T>> convertData2Node(List<T> data) {
List<Node<T>> list = new ArrayList<>();
for (T item : data) {
Node<T> node = new Node<>();
node.setIfEntryNode(item.getIfEntryNode());
node.setId(item.getId());
node.setParentId(item.getParentId());
node.setName(item.getName());
node.setResourceId(item.getImageResourceId());
node.setItem(item);
list.add(node);
}
linkNodes(list);
return list;
}
/**
* 挂子节点至相应父节点下
*/
private static <T extends Tree> void linkNodes(List<Node<T>> list) {
for (int i = 0; i < list.size(); i++) {
Node<T> n = list.get(i);
for (int j = i + 1; j < list.size(); j++) {
Node<T> m = list.get(j);
if (n.getParentId() == m.getId()) {
m.getChildren().add(n);
n.setParent(m);
continue;
}
if (m.getParentId() == n.getId()) {
n.getChildren().add(m);
m.setParent(n);
}
}
}
}
/**
* 根节点
*
* @param nodes 节点集合
* @param <T> T
* @return 根节点
*/
private static <T extends Tree> List<Node<T>> getRootNodes(List<Node<T>> nodes) {
List<Node<T>> root = new ArrayList<>();
for (Node<T> node : nodes) {
if (node.isRoot()) {
root.add(node);
}
}
return root;
}
/**
* 添某节点下全子节点
*/
private static <T extends Tree> void addNode(List<Node<T>> nodes, Node<T> node, int defaultExpandLevel, int currentLevel) {
nodes.add(node);
if (defaultExpandLevel == currentLevel) {
node.setExpand(true);
}
if (node.isLeaf()) {
return;
}
for (int i = 0; i < node.getChildren().size(); i++) {
addNode(nodes, node.getChildren().get(i), defaultExpandLevel, currentLevel + 1);
}
}
}
TreeItemClickListener
package function.tree;
import android.view.View;
/**
* @decs: TreeItemClickListener
* @date: 2018/9/7 15:52
* @version: v 1.0
*/
public interface TreeItemClickListener {
/**
* 点
*
* @param view 视图
* @param node 节点
*/
void onClick(View view, Node node);
/**
* 右点
*
* @param node 节点
*/
void onRightClick(Node node);
}
tree_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="@drawable/white_gray_button_en_r_selector"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/ivTreeItemLeft"
android:layout_width="@dimen/d48"
android:layout_height="match_parent"
android:contentDescription="@string/toDo"
android:scaleType="centerInside" />
<TextView
android:id="@+id/tvTreeItemName"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:textColor="@color/fontInput"
android:textSize="@dimen/s14"
tools:text="名称" />
<ImageView
android:id="@+id/ivTreeItemRight"
android:layout_width="@dimen/d48"
android:layout_height="match_parent"
android:contentDescription="@string/toDo"
android:scaleType="centerInside" />
</LinearLayout>
使用
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".drillingdataanalysis.DrillingDataAnalysisActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="@color/colorPrimary">
<ImageView
android:id="@+id/tvBasicConfigWellTypeBack"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:contentDescription="@string/toDo"
android:paddingLeft="@dimen/d12"
android:paddingRight="@dimen/d12"
app:srcCompat="@drawable/ic_top_back_white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/drillingDataAnalysis"
android:textColor="@color/background"
android:textSize="@dimen/s16" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rvDrillingDataAnalysis"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
android:scrollbars="none" />
</LinearLayout>
主代码
@BindView(R.id.rvDrillingDataAnalysis)
RecyclerView rvDrillingDataAnalysis;
private List<IfEntryNodeTree> ifEntryNodeTrees;
/*
false头项/true末项
*/
rvDrillingDataAnalysis.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
// 每item内容不改RecyclerView大小,此设提性能
rvDrillingDataAnalysis.setHasFixedSize(true);
/*
节点
*/
ifEntryNodeTrees = new ArrayList<>();
for (IFEntryNode ifEntryNode : ifEntryNodes) {
treeResult(ifEntryNode);
}
display();
/**
* 树结果
*
* @param ifEntryNode 节点
*/
private void treeResult(IFEntryNode ifEntryNode) {
LogUtils.e(ifEntryNode.getText() + Long.parseLong(ifEntryNode.getId()));
JsonElement jsonElement = new JsonParser().parse(ifEntryNode.getNodeJSON()).getAsJsonObject().get("parentId");
long parentId = "0-1".equals(jsonElement.getAsString()) ? 0 : jsonElement.getAsLong();
ifEntryNodeTrees.add(new IfEntryNodeTree(ifEntryNode, Long.parseLong(ifEntryNode.getId()), parentId, ifEntryNode.getText(), 0));
if (ifEntryNode.getChildNodes().size() > 0) {
for (IFEntryNode ifEntryNode1 : ifEntryNode.getChildNodes()) {
treeResult(ifEntryNode1);
}
}
}
/**
* 展示
*/
private void display() {
final TreeAdapter<IfEntryNodeTree> adapter = new TreeAdapter<>(this, ifEntryNodeTrees);
rvDrillingDataAnalysis.setAdapter(adapter);
// 额外
final List<IfEntryNodeTree> extra = new ArrayList<>();
extra.add(new IfEntryNodeTree(null, 0, 1, "测试", 0));
extra.add(new IfEntryNodeTree(null, 0, 1, "测试", 0));
extra.add(new IfEntryNodeTree(null, 0, 1, "测试", 0));
adapter.setListener(new TreeItemClickListener() {
@Override
public void onClick(View view, Node node) {
if (node.isLeaf()) {
IFIntegrationUtils.loadEntryView(DrillingDataAnalysisActivity.this, node.getIfEntryNode());
}
}
@Override
public void onRightClick(Node node) {
toastShort(node.getName());
if (node.getId() == 1) {
adapter.addChildrenById(1, extra);
}
}
});
}
效果
引申
较少层级用Brvah。
最后
以上就是寂寞乌龟最近收集整理的关于目录树(一)的全部内容,更多相关目录树(一)内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复