add show node tree
This commit is contained in:
parent
502d731489
commit
46eff0d904
@ -11,5 +11,6 @@
|
||||
android:name=".ui.DoricDevActivity"
|
||||
android:theme="@style/Theme.Design.Light.NoActionBar" />
|
||||
<activity android:name=".qrcode.activity.CaptureActivity" />
|
||||
<activity android:name=".ui.DoricShowNodeTreeActivity" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
@ -21,7 +21,6 @@ import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@ -50,6 +49,8 @@ import pub.doric.devkit.qrcode.DisplayUtil;
|
||||
import pub.doric.devkit.qrcode.activity.CaptureActivity;
|
||||
import pub.doric.devkit.qrcode.activity.CodeUtils;
|
||||
|
||||
import static pub.doric.devkit.ui.DoricShowNodeTreeActivity.DORIC_CONTEXT_ID_KEY;
|
||||
|
||||
public class DoricDevActivity extends AppCompatActivity implements DoricDev.StatusCallback {
|
||||
private int REQUEST_CODE = 100;
|
||||
private ContextCellAdapter cellAdapter;
|
||||
@ -363,6 +364,9 @@ public class DoricDevActivity extends AppCompatActivity implements DoricDev.Stat
|
||||
builder.show();
|
||||
}
|
||||
});
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
list.add("View source");
|
||||
list.add("Show node tree");
|
||||
if (DoricDev.getInstance().isInDevMode()) {
|
||||
if (context.getDriver() instanceof DoricDebugDriver) {
|
||||
actionMap.put("Stop debugging", new DialogInterface.OnClickListener() {
|
||||
|
@ -0,0 +1,100 @@
|
||||
package pub.doric.devkit.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.DoricContextManager;
|
||||
import pub.doric.devkit.R;
|
||||
import pub.doric.devkit.ui.treeview.DoricViewNodeLayoutItemType;
|
||||
import pub.doric.devkit.ui.treeview.DoricViewNodeTreeViewBinder;
|
||||
import pub.doric.devkit.ui.treeview.TreeNode;
|
||||
import pub.doric.devkit.ui.treeview.TreeViewAdapter;
|
||||
import pub.doric.shader.GroupNode;
|
||||
import pub.doric.shader.ViewNode;
|
||||
|
||||
public class DoricShowNodeTreeActivity extends AppCompatActivity {
|
||||
|
||||
public static final String DORIC_CONTEXT_ID_KEY = "DORIC_CONTEXT_ID";
|
||||
|
||||
private RecyclerView rv;
|
||||
private TreeViewAdapter adapter;
|
||||
|
||||
private DoricContext doricContext;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String contextId = getIntent().getStringExtra(DORIC_CONTEXT_ID_KEY);
|
||||
doricContext = DoricContextManager.getContext(contextId);
|
||||
|
||||
setContentView(R.layout.layout_show_node_tree);
|
||||
initView();
|
||||
initData();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
List<TreeNode> nodes = new ArrayList<>();
|
||||
TreeNode<DoricViewNodeLayoutItemType> root = new TreeNode<>(new DoricViewNodeLayoutItemType(doricContext.getRootNode()));
|
||||
|
||||
Queue<ViewNode> viewQueue = new LinkedList<>();
|
||||
Queue<TreeNode> treeQueue = new LinkedList<>();
|
||||
|
||||
viewQueue.offer(doricContext.getRootNode());
|
||||
treeQueue.offer(root);
|
||||
|
||||
while (!viewQueue.isEmpty()) {
|
||||
ViewNode viewNode = viewQueue.poll();
|
||||
TreeNode treeNode = treeQueue.poll();
|
||||
if (viewNode instanceof GroupNode) {
|
||||
GroupNode groupNode = (GroupNode) viewNode;
|
||||
for (int i = 0; i != groupNode.getChildNodes().size(); i++) {
|
||||
assert treeNode != null;
|
||||
TreeNode<DoricViewNodeLayoutItemType> temp = new TreeNode(new DoricViewNodeLayoutItemType((ViewNode) groupNode.getChildNodes().get(i)));
|
||||
treeNode.addChild(temp);
|
||||
|
||||
viewQueue.offer((ViewNode) groupNode.getChildNodes().get(i));
|
||||
treeQueue.offer(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nodes.add(root);
|
||||
|
||||
rv.setLayoutManager(new LinearLayoutManager(this));
|
||||
adapter = new TreeViewAdapter(nodes, Collections.singletonList(new DoricViewNodeTreeViewBinder()));
|
||||
// whether collapse child nodes when their parent node was close.
|
||||
// adapter.ifCollapseChildWhileCollapseParent(true);
|
||||
adapter.setOnTreeNodeListener(new TreeViewAdapter.OnTreeNodeListener() {
|
||||
@Override
|
||||
public boolean onClick(TreeNode node, RecyclerView.ViewHolder holder) {
|
||||
if (!node.isLeaf()) {
|
||||
//Update and toggle the node.
|
||||
onToggle(!node.isExpand(), holder);
|
||||
// if (!node.isExpand())
|
||||
// adapter.collapseBrotherNode(node);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onToggle(boolean isExpand, RecyclerView.ViewHolder holder) {
|
||||
DoricViewNodeTreeViewBinder.ViewHolder viewNodeTreeViewBinder = (DoricViewNodeTreeViewBinder.ViewHolder) holder;
|
||||
}
|
||||
});
|
||||
rv.setAdapter(adapter);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
rv = findViewById(R.id.show_node_tree_rv);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package pub.doric.devkit.ui.treeview;
|
||||
|
||||
import pub.doric.devkit.R;
|
||||
import pub.doric.shader.ViewNode;
|
||||
|
||||
public class DoricViewNodeLayoutItemType implements LayoutItemType {
|
||||
private final ViewNode viewNode;
|
||||
|
||||
public DoricViewNodeLayoutItemType(ViewNode viewNode) {
|
||||
this.viewNode = viewNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
return R.layout.layout_show_node_tree_cell;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package pub.doric.devkit.ui.treeview;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import pub.doric.devkit.R;
|
||||
|
||||
public class DoricViewNodeTreeViewBinder extends TreeViewBinder<DoricViewNodeTreeViewBinder.ViewHolder> {
|
||||
|
||||
@Override
|
||||
public ViewHolder provideViewHolder(View itemView) {
|
||||
return new ViewHolder(itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder holder, int position, TreeNode node) {
|
||||
DoricViewNodeLayoutItemType layoutItemType = (DoricViewNodeLayoutItemType) node.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
return R.layout.layout_show_node_tree_cell;
|
||||
}
|
||||
|
||||
public static class ViewHolder extends TreeViewBinder.ViewHolder {
|
||||
|
||||
public ViewHolder(View rootView) {
|
||||
super(rootView);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package pub.doric.devkit.ui.treeview;
|
||||
|
||||
public interface LayoutItemType {
|
||||
int getLayoutId();
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
package pub.doric.devkit.ui.treeview;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TreeNode<T extends LayoutItemType> implements Cloneable {
|
||||
private T content;
|
||||
private TreeNode parent;
|
||||
private List<TreeNode> childList;
|
||||
private boolean isExpand;
|
||||
private boolean isLocked;
|
||||
//the tree high
|
||||
private int height = UNDEFINE;
|
||||
|
||||
private static final int UNDEFINE = -1;
|
||||
|
||||
public TreeNode(@NonNull T content) {
|
||||
this.content = content;
|
||||
this.childList = new ArrayList<>();
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
if (isRoot())
|
||||
height = 0;
|
||||
else if (height == UNDEFINE)
|
||||
height = parent.getHeight() + 1;
|
||||
return height;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeaf() {
|
||||
return childList == null || childList.isEmpty();
|
||||
}
|
||||
|
||||
public void setContent(T content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public T getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public List<TreeNode> getChildList() {
|
||||
return childList;
|
||||
}
|
||||
|
||||
public void setChildList(List<TreeNode> childList) {
|
||||
this.childList.clear();
|
||||
for (TreeNode treeNode : childList) {
|
||||
addChild(treeNode);
|
||||
}
|
||||
}
|
||||
|
||||
public TreeNode addChild(TreeNode node) {
|
||||
if (childList == null)
|
||||
childList = new ArrayList<>();
|
||||
childList.add(node);
|
||||
node.parent = this;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean toggle() {
|
||||
isExpand = !isExpand;
|
||||
return isExpand;
|
||||
}
|
||||
|
||||
public void collapse() {
|
||||
if (isExpand) {
|
||||
isExpand = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void collapseAll() {
|
||||
if (childList == null || childList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (TreeNode child : this.childList) {
|
||||
child.collapseAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void expand() {
|
||||
if (!isExpand) {
|
||||
isExpand = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void expandAll() {
|
||||
expand();
|
||||
if (childList == null || childList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (TreeNode child : this.childList) {
|
||||
child.expandAll();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isExpand() {
|
||||
return isExpand;
|
||||
}
|
||||
|
||||
public void setParent(TreeNode parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public TreeNode getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public TreeNode<T> lock() {
|
||||
isLocked = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TreeNode<T> unlock() {
|
||||
isLocked = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isLocked() {
|
||||
return isLocked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TreeNode{" +
|
||||
"content=" + this.content +
|
||||
", parent=" + (parent == null ? "null" : parent.getContent().toString()) +
|
||||
", childList=" + (childList == null ? "null" : childList.toString()) +
|
||||
", isExpand=" + isExpand +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TreeNode<T> clone() throws CloneNotSupportedException {
|
||||
TreeNode<T> clone = new TreeNode<>(this.content);
|
||||
clone.isExpand = this.isExpand;
|
||||
return clone;
|
||||
}
|
||||
}
|
@ -0,0 +1,325 @@
|
||||
package pub.doric.devkit.ui.treeview;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class TreeViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
private static final String KEY_IS_EXPAND = "IS_EXPAND";
|
||||
private final List<? extends TreeViewBinder> viewBinders;
|
||||
private List<TreeNode> displayNodes;
|
||||
private int padding = 30;
|
||||
private OnTreeNodeListener onTreeNodeListener;
|
||||
private boolean toCollapseChild;
|
||||
|
||||
public TreeViewAdapter(List<? extends TreeViewBinder> viewBinders) {
|
||||
this(null, viewBinders);
|
||||
}
|
||||
|
||||
public TreeViewAdapter(List<TreeNode> nodes, List<? extends TreeViewBinder> viewBinders) {
|
||||
displayNodes = new ArrayList<>();
|
||||
if (nodes != null)
|
||||
findDisplayNodes(nodes);
|
||||
this.viewBinders = viewBinders;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从nodes的结点中寻找展开了的非叶结点,添加到displayNodes中。
|
||||
*
|
||||
* @param nodes 基准点
|
||||
*/
|
||||
private void findDisplayNodes(List<TreeNode> nodes) {
|
||||
for (TreeNode node : nodes) {
|
||||
displayNodes.add(node);
|
||||
if (!node.isLeaf() && node.isExpand())
|
||||
findDisplayNodes(node.getChildList());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return displayNodes.get(position).getContent().getLayoutId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext())
|
||||
.inflate(viewType, parent, false);
|
||||
if (viewBinders.size() == 1)
|
||||
return viewBinders.get(0).provideViewHolder(v);
|
||||
for (TreeViewBinder viewBinder : viewBinders) {
|
||||
if (viewBinder.getLayoutId() == viewType)
|
||||
return viewBinder.provideViewHolder(v);
|
||||
}
|
||||
return viewBinders.get(0).provideViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List<Object> payloads) {
|
||||
if (payloads != null && !payloads.isEmpty()) {
|
||||
Bundle b = (Bundle) payloads.get(0);
|
||||
for (String key : b.keySet()) {
|
||||
switch (key) {
|
||||
case KEY_IS_EXPAND:
|
||||
if (onTreeNodeListener != null)
|
||||
onTreeNodeListener.onToggle(b.getBoolean(key), holder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onBindViewHolder(holder, position, payloads);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
holder.itemView.setPaddingRelative(displayNodes.get(position).getHeight() * padding, 3, 3, 3);
|
||||
} else {
|
||||
holder.itemView.setPadding(displayNodes.get(position).getHeight() * padding, 3, 3, 3);
|
||||
}
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
TreeNode selectedNode = displayNodes.get(holder.getLayoutPosition());
|
||||
// Prevent multi-click during the short interval.
|
||||
try {
|
||||
long lastClickTime = (long) holder.itemView.getTag();
|
||||
if (System.currentTimeMillis() - lastClickTime < 500)
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
holder.itemView.setTag(System.currentTimeMillis());
|
||||
}
|
||||
holder.itemView.setTag(System.currentTimeMillis());
|
||||
|
||||
if (onTreeNodeListener != null && onTreeNodeListener.onClick(selectedNode, holder))
|
||||
return;
|
||||
if (selectedNode.isLeaf())
|
||||
return;
|
||||
// This TreeNode was locked to click.
|
||||
if (selectedNode.isLocked()) return;
|
||||
boolean isExpand = selectedNode.isExpand();
|
||||
int positionStart = displayNodes.indexOf(selectedNode) + 1;
|
||||
if (!isExpand) {
|
||||
notifyItemRangeInserted(positionStart, addChildNodes(selectedNode, positionStart));
|
||||
} else {
|
||||
notifyItemRangeRemoved(positionStart, removeChildNodes(selectedNode, true));
|
||||
}
|
||||
}
|
||||
});
|
||||
for (TreeViewBinder viewBinder : viewBinders) {
|
||||
if (viewBinder.getLayoutId() == displayNodes.get(position).getContent().getLayoutId())
|
||||
viewBinder.bindView(holder, position, displayNodes.get(position));
|
||||
}
|
||||
}
|
||||
|
||||
private int addChildNodes(TreeNode pNode, int startIndex) {
|
||||
List<TreeNode> childList = pNode.getChildList();
|
||||
int addChildCount = 0;
|
||||
for (TreeNode treeNode : childList) {
|
||||
displayNodes.add(startIndex + addChildCount++, treeNode);
|
||||
if (treeNode.isExpand()) {
|
||||
addChildCount += addChildNodes(treeNode, startIndex + addChildCount);
|
||||
}
|
||||
}
|
||||
if (!pNode.isExpand())
|
||||
pNode.toggle();
|
||||
return addChildCount;
|
||||
}
|
||||
|
||||
private int removeChildNodes(TreeNode pNode) {
|
||||
return removeChildNodes(pNode, true);
|
||||
}
|
||||
|
||||
private int removeChildNodes(TreeNode pNode, boolean shouldToggle) {
|
||||
if (pNode.isLeaf())
|
||||
return 0;
|
||||
List<TreeNode> childList = pNode.getChildList();
|
||||
int removeChildCount = childList.size();
|
||||
displayNodes.removeAll(childList);
|
||||
for (TreeNode child : childList) {
|
||||
if (child.isExpand()) {
|
||||
if (toCollapseChild)
|
||||
child.toggle();
|
||||
removeChildCount += removeChildNodes(child, false);
|
||||
}
|
||||
}
|
||||
if (shouldToggle)
|
||||
pNode.toggle();
|
||||
return removeChildCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return displayNodes == null ? 0 : displayNodes.size();
|
||||
}
|
||||
|
||||
public void setPadding(int padding) {
|
||||
this.padding = padding;
|
||||
}
|
||||
|
||||
public void ifCollapseChildWhileCollapseParent(boolean toCollapseChild) {
|
||||
this.toCollapseChild = toCollapseChild;
|
||||
}
|
||||
|
||||
public void setOnTreeNodeListener(OnTreeNodeListener onTreeNodeListener) {
|
||||
this.onTreeNodeListener = onTreeNodeListener;
|
||||
}
|
||||
|
||||
public interface OnTreeNodeListener {
|
||||
/**
|
||||
* called when TreeNodes were clicked.
|
||||
*
|
||||
* @return weather consume the click event.
|
||||
*/
|
||||
boolean onClick(TreeNode node, RecyclerView.ViewHolder holder);
|
||||
|
||||
/**
|
||||
* called when TreeNodes were toggle.
|
||||
*
|
||||
* @param isExpand the status of TreeNodes after being toggled.
|
||||
*/
|
||||
void onToggle(boolean isExpand, RecyclerView.ViewHolder holder);
|
||||
}
|
||||
|
||||
public void refresh(List<TreeNode> treeNodes) {
|
||||
displayNodes.clear();
|
||||
findDisplayNodes(treeNodes);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public Iterator<TreeNode> getDisplayNodesIterator() {
|
||||
return displayNodes.iterator();
|
||||
}
|
||||
|
||||
private void notifyDiff(final List<TreeNode> temp) {
|
||||
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() {
|
||||
@Override
|
||||
public int getOldListSize() {
|
||||
return temp.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewListSize() {
|
||||
return displayNodes.size();
|
||||
}
|
||||
|
||||
// judge if the same items
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
|
||||
return TreeViewAdapter.this.areItemsTheSame(temp.get(oldItemPosition), displayNodes.get(newItemPosition));
|
||||
}
|
||||
|
||||
// if they are the same items, whether the contents has bean changed.
|
||||
@Override
|
||||
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
|
||||
return TreeViewAdapter.this.areContentsTheSame(temp.get(oldItemPosition), displayNodes.get(newItemPosition));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
|
||||
return TreeViewAdapter.this.getChangePayload(temp.get(oldItemPosition), displayNodes.get(newItemPosition));
|
||||
}
|
||||
});
|
||||
diffResult.dispatchUpdatesTo(this);
|
||||
}
|
||||
|
||||
private Object getChangePayload(TreeNode oldNode, TreeNode newNode) {
|
||||
Bundle diffBundle = new Bundle();
|
||||
if (newNode.isExpand() != oldNode.isExpand()) {
|
||||
diffBundle.putBoolean(KEY_IS_EXPAND, newNode.isExpand());
|
||||
}
|
||||
if (diffBundle.size() == 0)
|
||||
return null;
|
||||
return diffBundle;
|
||||
}
|
||||
|
||||
// For DiffUtil, if they are the same items, whether the contents has bean changed.
|
||||
private boolean areContentsTheSame(TreeNode oldNode, TreeNode newNode) {
|
||||
return oldNode.getContent() != null && oldNode.getContent().equals(newNode.getContent())
|
||||
&& oldNode.isExpand() == newNode.isExpand();
|
||||
}
|
||||
|
||||
// judge if the same item for DiffUtil
|
||||
private boolean areItemsTheSame(TreeNode oldNode, TreeNode newNode) {
|
||||
return oldNode.getContent() != null && oldNode.getContent().equals(newNode.getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* collapse all root nodes.
|
||||
*/
|
||||
public void collapseAll() {
|
||||
// Back up the nodes are displaying.
|
||||
List<TreeNode> temp = backupDisplayNodes();
|
||||
//find all root nodes.
|
||||
List<TreeNode> roots = new ArrayList<>();
|
||||
for (TreeNode displayNode : displayNodes) {
|
||||
if (displayNode.isRoot())
|
||||
roots.add(displayNode);
|
||||
}
|
||||
//Close all root nodes.
|
||||
for (TreeNode root : roots) {
|
||||
if (root.isExpand())
|
||||
removeChildNodes(root);
|
||||
}
|
||||
notifyDiff(temp);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<TreeNode> backupDisplayNodes() {
|
||||
List<TreeNode> temp = new ArrayList<>();
|
||||
for (TreeNode displayNode : displayNodes) {
|
||||
try {
|
||||
temp.add(displayNode.clone());
|
||||
} catch (CloneNotSupportedException e) {
|
||||
temp.add(displayNode);
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
public void collapseNode(TreeNode pNode) {
|
||||
List<TreeNode> temp = backupDisplayNodes();
|
||||
removeChildNodes(pNode);
|
||||
notifyDiff(temp);
|
||||
}
|
||||
|
||||
public void collapseBrotherNode(TreeNode pNode) {
|
||||
List<TreeNode> temp = backupDisplayNodes();
|
||||
if (pNode.isRoot()) {
|
||||
List<TreeNode> roots = new ArrayList<>();
|
||||
for (TreeNode displayNode : displayNodes) {
|
||||
if (displayNode.isRoot())
|
||||
roots.add(displayNode);
|
||||
}
|
||||
//Close all root nodes.
|
||||
for (TreeNode root : roots) {
|
||||
if (root.isExpand() && !root.equals(pNode))
|
||||
removeChildNodes(root);
|
||||
}
|
||||
} else {
|
||||
TreeNode parent = pNode.getParent();
|
||||
if (parent == null)
|
||||
return;
|
||||
List<TreeNode> childList = parent.getChildList();
|
||||
for (TreeNode node : childList) {
|
||||
if (node.equals(pNode) || !node.isExpand())
|
||||
continue;
|
||||
removeChildNodes(node);
|
||||
}
|
||||
}
|
||||
notifyDiff(temp);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package pub.doric.devkit.ui.treeview;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public abstract class TreeViewBinder<VH extends RecyclerView.ViewHolder> implements LayoutItemType {
|
||||
public abstract VH provideViewHolder(View itemView);
|
||||
|
||||
public abstract void bindView(VH holder, int position, TreeNode node);
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public ViewHolder(View rootView) {
|
||||
super(rootView);
|
||||
}
|
||||
|
||||
protected <T extends View> T findViewById(@IdRes int id) {
|
||||
return itemView.findViewById(id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/show_node_tree_rv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/node_type_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
Reference in New Issue
Block a user