public class TreeLayout extends ViewGroup {
Tree tree;
int mDy = 60;
int mDx = 100;
private ScaleGestureDetector mScaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
double scaleFactor = detector.getScaleFactor();
float old = TreeLayout.this.getScaleX();
if (Math.abs(scaleFactor - old) > 0.6 || Math.abs(scaleFactor - old) < 0.02) {
//忽略
} else {
TreeLayout.this.setScaleX(detector.getScaleFactor());
TreeLayout.this.setScaleY(detector.getScaleFactor());
}
return false;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
});
private int lastX = 0;
private int lastY = 0;
private int mode = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
int currentX = (int) event.getRawX();//获得手指当前的坐标,相对于屏幕
int currentY = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mode = 1;
break;
case MotionEvent.ACTION_UP:
mode = 0;
break;
case MotionEvent.ACTION_POINTER_UP:
//将模式进行为负数这样,多指下,抬起不会触发移动
mode = -2;
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode += 1;
break;
case MotionEvent.ACTION_MOVE:
if (mode >= 2) {
//缩放
//mScaleGestureDetector.onTouchEvent(event);
} else if (mode == 1) {
int deltaX = currentX - lastX;
int deltaY = currentY - lastY;
int translationX = (int) getTranslationX() + deltaX;
int translationY = (int) getTranslationY() + deltaY;
setTranslationX(translationX);
setTranslationY(translationY);
}
break;
}
lastX = currentX;
lastY = currentY;
return mScaleGestureDetector.onTouchEvent(event);
}
public TreeLayout(Context context) {
super(context);
}
public TreeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TreeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TreeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int size = getChildCount();
for (int i = 0; i < size; i++) {
measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
}
mCurLine = 0;
minTop = Integer.MAX_VALUE;
maxBottom = 0;
// 深度搜索确定每一个节点的 top
deep(this, tree.getTreeRoot(), mCurLine);
minLeft = Integer.MAX_VALUE;
maxRight = 0;
List<TreeNode> childList = new ArrayList<>();
childList.add(tree.getTreeRoot());
// 深度搜索确定每一个节点的 start
width(this, childList );
setMeasuredDimension(maxRight - minLeft,maxBottom - minTop + 2 * mDy);
}
private int minLeft = Integer.MAX_VALUE;
private int maxRight = 0;
private void width(TreeLayout treeLayout, List<TreeNode> childList) {
List<TreeNode> nextChildList = new ArrayList<>();
for (TreeNode child : childList) {
TreeNode parent = child.getParent();
nextChildList.addAll(child.getChildNodes());
if (parent == null) {
View childView = findNodeViewFromNodeModel(child);
childView.layout(0, childView.getTop(), 0 + childView.getMeasuredWidth(), childView.getBottom());
minLeft = 0;
continue;
}
View parentView = findNodeViewFromNodeModel(parent);
View childView = findNodeViewFromNodeModel(child);
childView.layout(parentView.getRight() + mDx, childView.getTop(),parentView.getRight() + mDx + childView.getMeasuredWidth(), childView.getBottom());
if (minLeft > parentView.getRight() + mDx) {
minLeft = parentView.getRight() + mDx;
}
if (maxRight < parentView.getRight() + mDx + childView.getMeasuredWidth()) {
maxRight = parentView.getRight() + mDx + childView.getMeasuredWidth();
}
}
if (nextChildList.size() > 0) {
width(treeLayout, nextChildList);
}
}
private int mCurLine = 0;
private int minTop = Integer.MAX_VALUE;
private int maxBottom = 0;
private void deep(TreeLayout treeView, TreeNode<String> rootNode, int curLine) {
if (rootNode.getChildNodes().size() == 0) {
View leafView = treeView.findNodeViewFromNodeModel(rootNode);
leafView.layout(leafView.getLeft(), curLine + mDy,leafView.getRight(), curLine + mDy + leafView.getMeasuredHeight());
mCurLine = curLine + mDy + leafView.getMeasuredHeight();
if (minTop > curLine + mDy) {
minTop = curLine + mDy;
}
if (maxBottom < curLine + mDy + leafView.getMeasuredHeight()) {
maxBottom = curLine + mDy + leafView.getMeasuredHeight();
}
return;
}
for ( TreeNode<String> curNode : rootNode.getChildNodes()) {
deep(treeView, curNode, mCurLine);
}
View rootView = treeView.findNodeViewFromNodeModel(rootNode);
View firstView = treeView.findNodeViewFromNodeModel(rootNode.getChildNodes().get(0));
View lastView = treeView.findNodeViewFromNodeModel(rootNode.getChildNodes().get(rootNode.getChildNodes().size() - 1));
int mid = (lastView.getBottom() + firstView.getTop()) / 2;
int top = mid - rootView.getMeasuredHeight() / 2;
int bot = mid + rootView.getMeasuredHeight() / 2;
rootView.layout(rootView.getLeft(), top, rootView.getRight(), bot);
if (bot > mCurLine) {
mCurLine = bot;
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (tree.getTreeRoot() != null) {
drawTreeLine(canvas, tree.getTreeRoot());
}
}
private void drawTreeLine(Canvas canvas, TreeNode<String> root) {
TreeNoteView fatherView = (TreeNoteView) findNodeViewFromNodeModel(root);
if (fatherView != null) {
List<TreeNode> childNodes = root.getChildNodes();
for (TreeNode<String> node : childNodes) {
//连线
drawLineToView(canvas, fatherView, findNodeViewFromNodeModel(node));
//递归
drawTreeLine(canvas, node);
}
}
}
private void drawLineToView(Canvas canvas, View from, View to) {
if (to.getVisibility() == GONE) {
return;
}
Paint mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
float width = 2f;
mPaint.setStrokeWidth(6);
mPaint.setColor(Color.BLACK);
int top = from.getTop();
int formY = top + from.getMeasuredHeight() / 2;
int formX = from.getRight();
int top1 = to.getTop();
int toY = top1 + to.getMeasuredHeight() / 2;
int toX = to.getLeft();
Path mPath = new Path();
mPath.reset();
mPath.moveTo(formX, formY);
mPath.quadTo(toX, toY, toX, toY);
canvas.drawPath(mPath, mPaint);
}
public Tree getTree() {
return tree;
}
public void setTree(Tree tree) {
this.tree = tree;
deepAddChildView(tree.getTreeRoot());
}
private void deepAddChildView(TreeNode treeRoot) {
if (treeRoot == null) {
return;
}
for (Object node : treeRoot.getChildNodes()) {
TreeNode curNode = (TreeNode)node;
deepAddChildView(curNode);
}
TreeNoteView treeNoteView = new TreeNoteView(getContext());
treeNoteView.setTreeNode(treeRoot);
addView(treeNoteView);
}
public View findNodeViewFromNodeModel(TreeNode<String> nodeModel) {
View view = null;
int size = getChildCount();
for (int i = 0; i < size; i++) {
View childView = getChildAt(i);
if (childView instanceof TreeNoteView) {
TreeNode<String> treeNode = ((TreeNoteView) childView).getTreeNode();
if (treeNode == nodeModel) {
view = childView;
continue;
}
}
}
return view;
}
}