Android思维导图布局:效果展示及使用方法

思维导图布局的前身是树形布局,对树形布局基本使用还不太了解的朋友可以先看看我写的树形布局系列教程,了解了树形布局的使用方法后再来阅读本文章。

先睹为快

来看看效果吧,横向效果如下:
在这里插入图片描述
纵向效果如下:(布局可拖拽,后面会讲解)
在这里插入图片描述

基本使用

首先导入库。

allprojects { 
	repositories {
	 	 ...
	 	 maven { url 'https://jitpack.io'
		 }
	} 
}

dependencies { 
	implementation 'com.github.PYJTLK:MindMapViewTest:1.2'
}

为了方便讲解,下面来实现如下的效果,先写布局代码。
在这里插入图片描述
注意下面的代码,MindMapLayout是思维导图布局,TreeLayout是树形布局。一定要按照如下的方式摆放,否则会报错。
左树 + 根 + 右树 或者 上树 + 根 + 下树
app:orientation决定思维导图的方向
app:mapLocked锁定思维导图,后面会讲它的作用

<com.pyjtlk.widget.MindMapLayout
        android:id="@+id/mindMapLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#A0A0"
        app:orientation="horizontal"
        app:mapLocked="false">

        <!--左树-->
        <com.pyjtlk.widget.TreeLayout
            android:id="@+id/treeView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:treeDirection="downToUp"
            app:levelInterval="50dp">

            <Button
                android:layout_width="80dp"
                android:layout_height="40dp"
                android:text="Node"/>

            <Button
                android:layout_width="80dp"
                android:layout_height="40dp"
                android:text="Node"
                android:layout_margin="10dp"/>

            <Button
                android:layout_width="80dp"
                android:layout_height="40dp"
                android:text="Node"
                android:layout_margin="10dp"/>
        </com.pyjtlk.widget.TreeLayout>

        <!--根-->
        <Button
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:text="ROOT"/>
        
        <!--右树-->
        <com.pyjtlk.widget.TreeLayout
            android:id="@+id/treeView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:treeDirection="upToDown"
            app:levelInterval="50dp">

            <Button
                android:layout_width="80dp"
                android:layout_height="40dp"
                android:text="Node"/>

            <Button
                android:layout_width="80dp"
                android:layout_height="40dp"
                android:text="Node"
                android:layout_margin="10dp"/>

            <Button
                android:layout_width="80dp"
                android:layout_height="40dp"
                android:text="Node"
                android:layout_margin="10dp"/>

        </com.pyjtlk.widget.TreeLayout>
    </com.pyjtlk.widget.MindMapLayout>

接下来写java代码。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mindMapLayout = findViewById(R.id.mindMapLayout);
	
		//1
        CurveDrawer documentLineDrawer = new CurveDrawer(6,Color.WHITE);
        //2
        RectFrameDrawer rectFrameDrawer = new RectFrameDrawer(documentLineDrawer,6,Color.WHITE);
        //3
        ConnectPointDrawer connectPointDrawer = new ConnectPointDrawer(rectFrameDrawer,12, Color.WHITE);
        mindMapLayout.setDecorDrawer(connectPointDrawer);
    }

代码1、2、3都是装饰绘制器,思维导图布局上面的连接线、方框等装饰物都是由它们绘制出来的,后面会讲它们的使用方法。

写好了运行一下就可以了。

布局参数

思维导图布局的参数有两个。

参数说明
app:orientation决定思维导图的方向:horizontal(水平方向),vertical(竖直方向)
app:mapLocked是否锁定布局,解锁状态下布局可以拖拽

常用方法

方法说明
setDecorDrawer设置装饰绘制器
setOrientation设置方向
lockMap锁定/解锁布局,解锁后布局可拖拽,子控件将无法接收滑动事件
skipDrawDecorator跳过装饰物绘制

高级用法

1.自定义装饰物绘制器

我们可以通过继承NodeDecoratorDrawer类来实现想要的绘制效果,例如实现结点直线连接。
在这里插入图片描述
直线绘制器的代码如下。

public class DirectLineDrawer extends NodeDecoratorDrawer {
    protected int mLineWidth;
    protected int mColor;
    protected int mStartX;
    protected int mStartY ;
    protected int mEndX;
    protected int mEndY;

    public DirectLineDrawer(int lineWidth, int color){
        this(null,lineWidth,color);
    }

    public DirectLineDrawer(NodeDecoratorDrawer sourceDecorator, int lineWidth, int color){
        super(sourceDecorator);
        mLineWidth = lineWidth;
        mColor = color;
    }

    @Override
    protected void onDrawDecorator(Canvas canvas, Paint paint, Rect start, Rect end, int direction) {
        switch(direction){
            case Direction.DIRECTION_LEFT_TO_RIGHT:
                mStartX = start.right;
                mEndX = end.left;
                mStartY = (start.top + start.bottom) / 2;
                mEndY = (end.top + end.bottom)  /2;
                break;

            case Direction.DIRECTION_RIGHT_TO_LEFT:
                mStartX = start.left;
                mEndX = end.right;
                mStartY = (start.top + start.bottom) / 2;
                mEndY = (end.top + end.bottom)  /2;
                break;

            case Direction.DIRECTION_UP_TO_DOWN:
                mStartX = (start.right + start.left) / 2;
                mEndX = (end.right + end.left) / 2;
                mStartY = start.bottom;
                mEndY = end.top;
                break;

            case Direction.DIRECTION_DOWN_TO_UP:
                mStartX = (start.right + start.left) / 2;
                mEndX = (end.right + end.left) / 2;
                mStartY = start.top;
                mEndY = end.bottom;
                break;
        }

        paint.setColor(mColor);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(mLineWidth);
        canvas.drawLine(mStartX,mStartY,mEndX,mEndY,paint);
    }

    public int getLineWidth() {
        return mLineWidth;
    }

    public void setLineWidth(int lineWidth) {
        this.mLineWidth = lineWidth;
    }

    public int getColor() {
        return mColor;
    }

    public void setmColor(int color) {
        mColor = color;
    }
}

不仅如此,绘制器是可以功能叠加的。

//直线绘制器
DirectLineDrawer directLineDrawer = new DirectLineDrawer(6,Color.WHITE);
//方框绘制器,在布局子控件外围绘制一个方框        
RectFrameDrawer rectFrameDrawer = new RectFrameDrawer(directLineDrawer,6,Color.WHITE);
//圆点绘制器
ConnectPointDrawer connectPointDrawer = new ConnectPointDrawer(rectFrameDrawer,12, Color.WHITE);
mindMapLayout.setDecorDrawer(connectPointDrawer);

在这里插入图片描述

2.布局拖拽

在布局文件中设置app:mapLocked=“false” 或 调用lockMap(false) 方法就可以解锁布局。布局解锁后就可以拖拽了。注意,解锁后滑动事件会被思维导图布局拦截,布局上锁了子控件才能接收到滑动事件。

最后

思维导图布局的使用教程就到这里了,前面说过思维导图布局的前身是树形布局,二者的用法其实非常相似,对源码感兴趣的朋友可以到Github项目里看看,喜欢这个布局控件的话可以star一下以示鼓励。

实现Android端的简易思维导图。可以保存数据。编辑树形图。建立模型主要模型结构相对简单:TreeModel,NoteModel,NoteView,TreeView。核心实现分布如下:2017-07-01TreeModel:树形结构的存储,树形结构的遍历,添加、删除节点;NoteModel:节点关联的指向,和Parent的指向;TreeView :绘制树形结构,对树形结构位置的纠正,实现View层的添加,删除,note关联绘制;NoteView:显示text;编写位置计算核心代码在核心代码中,我想和大家分享的是TreeView如何对多种Style(树形形状)进行适配的问题。因为我们的树形结构的表达多种的,有的是一个半树形图,有点是圆形展开的等。对于这个问题,作为程序员如何进行解耦能,采用Interface进行解构适配,统一行为。所以在这里我写了一个TreeLayoutManager进行管理树形的位置表达。这里我实现了一个RightTreeLayoutManager。代码概况如下:接口public interface TreeLayoutManager {     /**      * 进行树形结构的位置计算      */     void onTreeLayout(TreeView treeView);     /**      * 位置分布好后的回调,用于确认ViewGroup的大小      */     ViewBox onTreeLayoutCallBack();     /**      * 修正位置      *      * @param treeView      * @param next      */     void correctLayout(TreeView treeView, NodeView next); }实现public class RightTreeLayoutManager implements TreeLayoutManager{     final int msg_standard_layout = 1;     final int msg_correct_layout = 2;     final int msg_box_call_back = 3;     private ViewBox mViewBox;     private int mDy;     private int mDx;     private int mHeight;     public RightTreeLayoutManager(int dx, int dy, int height) {         mViewBox = new ViewBox();         this.mDx = dx;         this.mDy = dy;         this.mHeight = height;     }     @Override     public void onTreeLayout(final TreeView treeView) {         final TreeModel mTreeModel = treeView.getTreeModel();         if (mTreeModel != null) {             View rootView = treeView.findNodeViewFromNodeModel(mTreeModel.getRootNode());             if (rootView != null) {                 rootTreeViewLayout((NodeView) rootView);             }             mTreeModel.addForTreeItem(new ForTreeItem<NodeModel>() {                 @Override                 public void next(int msg, NodeModel next) {                     doNext(msg, next, treeView);                 }             });             //基本布局             mTreeModel.ergodicTreeInWith(msg_standard_layout);   
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值