利用组合模式与访问者模式实现Android树形控件(多层级,可拖拽)

效果图如上,实现思路有三点。

1.使用组合模式组织部门员工数据结构。

2.使用访问者模式定义并解耦对部门、员工元素的操作。

3.使用Android的拖放框架,能够允许用户使用图形化的拖放手势,把数据从当前布局中的一个View对象中移到另一个View对象中。

代码:叶节点

public class Node implements NodeAccept, Serializable {

    //节点层级
    private int layer;

    //节点名称
    private String nodeName;

    //父节点
    private NodeGroup parentNode;

    public Node(String name) {
        this.nodeName = name;
    }

    @Override
    public void accept(NodeVisitor visitor) {
        visitor.visit(this);
    }

    //获得父节点
    public NodeGroup getParent() {
        return parentNode;
    }

    //从父节点移除自己
    public void destory() {
        getParent().removeChild(this);
    }
    
    public String getNodeName() {
        return nodeName;
    }

    public void setNodeName(String nodeName) {
        this.nodeName = nodeName;
    }

    public void setParentNode(NodeGroup parentNode) {
        this.parentNode = parentNode;
    }

    public int getLayer() {
        return layer;
    }

    public void setLayer(int layer) {
        this.layer = layer;
    }

}
枝节点
public class NodeGroup extends Node implements NodeManager, NodeAccept {

    //是否是根节点
    private boolean root;

    //子节点存储
    private List<Node> components;

    public NodeGroup(String name) {
        super(name);
        components = new ArrayList<>();
    }

    public NodeGroup(String name, boolean root) {
        super(name);
        this.root = root;
        components = new ArrayList<>();
    }

    @Override
    public void setLayer(int layer) {
        super.setLayer(layer);
        for (Node node:components){
            node.setLayer(getLayer() + 1);
        }
    }

    @Override
    public void addChild(Node node) {
        node.setParentNode(this);
        node.setLayer(getLayer() + 1);
        components.add(node);
    }

    @Override
    public void removeChild(Node node) {
        node.setParentNode(null);
        components.remove(node);
    }

    @Override
    public List<Node> getAllChild() {
        return components;
    }

    @Override
    public Node getChildAt(int index) {
        return components.get(index);
    }

    @Override
    public int getChildCount() {
        return components.size();
    }

    @Override
    public void accept(NodeVisitor visitor) {
        visitor.visit(this);
    }

    @Override
    public NodeGroup getParent() {
        if (isRoot()) {
            throw new RuntimeException("node is root");
        }
        return super.getParent();
    }

    @Override
    public void destory() {
        if (isRoot()) {
            return;
        }
        super.destory();
    }

    public boolean isRoot() {
        return root;
    }

    public void setRoot(boolean root) {
        this.root = root;
    }

}
访问接口
public interface NodeAccept {
    //接受访问者
    void accept(NodeVisitor visitor);
}
枝节点接口
public interface NodeManager {

    //添加子节点
    void addChild(Node node);

    //删除子节点
    void removeChild(Node node);

    //获得所有子节点
    List<Node> getAllChild();

    //根据下标获得子节点
    Node getChildAt(int index);

    //获取子节点个数
    int getChildCount();

}
访问者
public interface NodeVisitor {
    //访问节点
    void visit(Node node);
}
treeView访问者
public class TreeViewVisitor implements NodeVisitor {

    private Context mContext;

    private Node dropNode;
    private ViewGroup rootView;

    private OnDragChange onDragChange;
    private HashMap<String, LinearLayout> list;

    public TreeViewVisitor(Context context) {
        this.mContext = context;
        this.list = new HashMap<>();
    }

    @Override
    public void visit(Node node) {
        LinearLayout parent = list.get(node.getParent().getNodeName());
        parent.addView(getTextView(node));
    }

    @Override
    public void visit(NodeGroup nodeGroup) {
        if (nodeGroup.isRoot()) {
            createNodeGroupView(nodeGroup);
        } else {
            if (list.containsKey(nodeGroup.getParent().getNodeName())) {
                LinearLayout parentLayout = list.get(nodeGroup.getParent().getNodeName());
                parentLayout.addView(createNodeGroupView(nodeGroup));
            } else {
                createNodeGroupView(nodeGroup);
            }
        }
        List<Node> nodes = nodeGroup.getAllChild();
        for (Node e : nodes) {
            e.accept(this);
        }
    }

    //获取任意节点下的view
    public ViewGroup getShowView(Node node) {
        rootView = list.get(node.getNodeName());
        return rootView;
    }

    //创建NodeGrop组视图
    private LinearLayout createNodeGroupView(final NodeGroup nodeGroup) {
        TextView textView = getTextView(nodeGroup);
        LinearLayout parentLayout = getParentLayout();
        parentLayout.addView(textView);
        parentLayout.setOnDragListener(new View.OnDragListener() {  //拖拽
            @Override
            public boolean onDrag(View v, DragEvent event) {
                switch (event.getAction()) {
                    case DragEvent.ACTION_DRAG_STARTED:
                        break;
                    case DragEvent.ACTION_DRAG_ENTERED:
                        break;
                    case DragEvent.ACTION_DRAG_EXITED:
                        break;
                    case DragEvent.ACTION_DRAG_LOCATION:
                        break;
                    case DragEvent.ACTION_DRAG_ENDED:
                        break;
                    case DragEvent.ACTION_DROP:
                        if (!nodeGroup.getNodeName().equals(dropNode.getNodeName()) &&
                                !dropNode.getParent().getNodeName().equals(nodeGroup.getNodeName())) {
                            Toast.makeText(mContext,dropNode.getNodeName() + "移动至" + nodeGroup.getNodeName(),Toast.LENGTH_SHORT).show();
                            dropNode.destory();
                            nodeGroup.addChild(dropNode);
                            if (onDragChange != null) {
                                onDragChange.dragChange();
                            }
                        }
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
        textView.setOnClickListener(new MyOnClickListener(parentLayout));
        list.put(nodeGroup.getNodeName(), parentLayout);
        return parentLayout;
    }

    //创建布局
    private LinearLayout getParentLayout() {
        LinearLayout linearLayout = new LinearLayout(mContext);
        linearLayout.setOrientation(LinearLayout.VERTICAL);
        return linearLayout;
    }

    //创建文本视图
    private TextView getTextView(final Node node) {
        TextView textView = new TextView(mContext);
        if (node instanceof NodeGroup) {
            bindDrawable(textView, R.mipmap.down);
        }
        textView.setBackgroundResource(R.drawable.shape_circle);
        textView.setPadding(50 * node.getLayer() + 15, 30, 30, 30);
        textView.setTextSize(17);
        textView.setText(node.getNodeName() + " (层级" + node.getLayer() + ")");
        //长按拖拽
        textView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                dropNode = node;
                view.setTag(node.getNodeName());
                ClipData.Item item = new ClipData.Item(node.getNodeName());
                String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};
                ClipData dragData = new ClipData(view.getTag().toString(), mimeTypes, item);
                View.DragShadowBuilder myShadow = new View.DragShadowBuilder(view);
                view.startDrag(dragData, myShadow, null, 0);
                return true;
            }
        });
        return textView;
    }

    //数据拖动后回调
    public interface OnDragChange {
        void dragChange();
    }
    
    public void setOnDragChange(OnDragChange onDragChange) {
        this.onDragChange = onDragChange;
    }
    
    //点击隐藏显示
    private class MyOnClickListener implements View.OnClickListener {
        private LinearLayout layout;
        public MyOnClickListener(LinearLayout linearLayout) {
            this.layout = linearLayout;
        }
        @Override
        public void onClick(View view) {
            int childCount = layout.getChildCount();
            for (int i = 0; i < childCount; i++) {
                if (i != 0) {
                    int visibility = layout.getChildAt(i).getVisibility();
                    TextView textView = (TextView) view;
                    if (visibility == View.GONE) {
                        bindDrawable(textView, R.mipmap.down);
                        layout.getChildAt(i).setVisibility(View.VISIBLE);
                    } else {
                        bindDrawable(textView, R.mipmap.up);
                        layout.getChildAt(i).setVisibility(View.GONE);
                    }
                }
            }
        }
    }
    
    //绑定展开,伸展图片
    private void bindDrawable(TextView textView, int id) {
        Drawable drawable = textView.getContext().getResources().getDrawable(id);
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        textView.setCompoundDrawables(drawable, null, null, null);
        textView.setCompoundDrawablePadding(15);
    }
}
执行代码
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final LinearLayout contentView = new LinearLayout(this);
        setContentView(contentView);

        Node A1 = new Node("安卓1");
        Node A2 = new Node("安卓2");
        Node P1 = new Node("php1");
        Node P2 = new Node("php2");
        Node C1 = new Node("产品1");
        final NodeGroup aiju = new NodeGroup("爱聚公司", true);
        NodeGroup development = new NodeGroup("研发部");
        NodeGroup product = new NodeGroup("产品部");
        NodeGroup android = new NodeGroup("安卓小组");
        NodeGroup php = new NodeGroup("PHP小组");

        aiju.addChild(development);
        aiju.addChild(product);

        development.addChild(android);
        development.addChild(php);
        product.addChild(C1);

        php.addChild(P1);
        php.addChild(P2);

        android.addChild(A1);
        android.addChild(A2);

        final TreeViewVisitor treeViewVisitor = new TreeViewVisitor(this);
        aiju.accept(treeViewVisitor);
        treeViewVisitor.setOnDragChange(new TreeViewVisitor.OnDragChange() {
            @Override
            public void dragChange() {
                aiju.accept(show);
                contentView.removeAllViews();
                ViewGroup viewGroup = show.getShowView(aiju);
                contentView.addView(viewGroup);
            }
        });

        ViewGroup viewGroup = show.getShowView(treeViewVisitor);
        contentView.addView(viewGroup);
}
在学习组合模式和访问者模式中产生想法并实现了组件的雏形,并未使用到项目,希望各位大神提供宝贵意见。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值