思维导图布局的前身是树形布局,对树形布局基本使用还不太了解的朋友可以先看看我写的树形布局系列教程,了解了树形布局的使用方法后再来阅读本文章。
先睹为快
来看看效果吧,横向效果如下:
纵向效果如下:(布局可拖拽,后面会讲解)
基本使用
首先导入库。
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一下以示鼓励。