Android 动态关系图

1、先上一个效果图:

Android 动态关系图_第1张图片

2、最近做了一个类似企查查的关系图,要求是绘制人物节点,节点之间关系标示,布局可缩放,单个节点可拖动。需求背景交代完毕。

3、简单说一下思路,自定义View ,继承SurfaceView,这种设计不会影响主线程的操作,surfaceView拥有独立的Cavans,绘制效率高,动画效果流畅。

4、开始上代码

      第一步,画圆,这个简单,需要的是外部传入节点的信息,xy位置及半径大小。这个不难,需要注意的是节点内部的文字需要做调整,保证文字在圆心位置,至少看起来是。


    //关系图 圆形
    private void drawCircle(Canvas canvas, int radius, int positionX, int positionY, int circleColor, int fillColor, String text, int textColor, int textSize) {
        mPaint.setColor(circleColor);
        canvas.drawCircle(positionX, positionY, radius, mPaint);
        mPaint.setColor(fillColor);
        canvas.drawCircle(positionX, positionY, radius - 1, mPaint);

        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setColor(textColor);


        mPaint.setTextSize(textSize);

        positionY += 5;
        if (text.length() > 0 && text.length() <= 5) {
            canvas.drawText(text, positionX, positionY, mPaint);
        } else if (text.length() > 5 && text.length() <= 10) {
            canvas.drawText(text.substring(0, 3), positionX, positionY - 25, mPaint);
            canvas.drawText(text.substring(3, text.length()), positionX, positionY, mPaint);
        } else if (text.length() > 10 && text.length() <= 15) {
            canvas.drawText(text.substring(0, 3), positionX, positionY - 25, mPaint);
            canvas.drawText(text.substring(3, 8), positionX, positionY, mPaint);
            canvas.drawText(text.substring(8, text.length()), positionX, positionY + 25, mPaint);
        } else if (text.length() > 15) {
            canvas.drawText(text.substring(0, 3), positionX, positionY - 50, mPaint);
            canvas.drawText(text.substring(3, 8), positionX, positionY - 25, mPaint);
            canvas.drawText(text.substring(8, 14), positionX, positionY, mPaint);
            canvas.drawText(text.substring(14, text.length()), positionX, positionY + 25, mPaint);
        }
        canvas.save();
        mPaint.reset();
    }

第二步,画节点与节点间的连线,这里有个问题就是,知道两个圆心的位置,节点半径,但是需要计算连线与节点圆的交点位置。

    private void caculate(int startX, int startY, int r1, int endX, int endY, int r2, String text, int textColor, int lineColor, int textSize) {

        double h = Math.abs(endY - startY);
        double w = Math.abs(endX - startX);

        double degree = Math.toDegrees(Math.atan(w / h));

//        Log.d(TAG, "CACULATE -- degree " + degree + "  " + (r1 * Math.sin(Math.PI / 180 * 30)));
        int x11 = 0, y11 = 0, x22 = 0, y22 = 0;
        if (startX > endX) {
            x11 = (int) (startX - (r1 * Math.sin(Math.PI / 180 * degree)));
            x22 = (int) (endX + (r2 * Math.sin(Math.PI / 180 * degree)));
        } else {
            x11 = (int) (startX + (r1 * Math.sin(Math.PI / 180 * degree)));
            x22 = (int) (endX - (r2 * Math.sin(Math.PI / 180 * degree)));
        }

        if (startY < endY) {
            y11 = (int) (startY + (r1 * Math.cos(Math.PI / 180 * degree)));
            y22 = (int) (endY - (r2 * Math.cos(Math.PI / 180 * degree)));
        } else {
            y11 = (int) (startY - (r1 * Math.cos(Math.PI / 180 * degree)));
            y22 = (int) (endY + (r2 * Math.cos(Math.PI / 180 * degree)));
        }
        drawAL(canvas, x11, y11, x22 - 3, y22 - 3, text, textColor, lineColor, textSize);
    }

我给画个草图,帮助理解 ,这就是三角形的部分知识,不懂的同学问问初中的表弟,Math类包含很多计算方法,思路就是求出一个角度,算出两圆心连线与各节点的交点位置,这里看看代码,不再赘述。

Android 动态关系图_第2张图片

第三步,画箭头,这个不难,可以去百度找找,很多类似代码,根据需求改吧改吧。晚点我会上这个View的整体代码,这里就不贴了。

 到这里,基本的绘制工作完成,不难,接下来确定三个方法,

  1、画布随手指拖动

   这个问题处理的方法是,确定好一个点,比如我选择屏幕中心点,作为你的基准点,在你拖动的时候,根据手指拖动的距离去改变这个点坐标,传入绘制操作里是,画布就动起来了。

 class DrawThread extends Thread {
        @Override
        public void run() {
            while (flag) {
                long start = System.currentTimeMillis();
                drawItems();
                long end = System.currentTimeMillis();
                try {
                    if (end - start < 50) {
                        Thread.sleep(50 - (end - start));
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void drawItems() {
        try {
            canvas = mHolder.lockCanvas();
            if (canvas != null) {
                canvas.drawColor(bacColor);
                canvas.save();
                canvas.scale(rate, rate, cX, cY);
                if (null != lines && lines.size() != 0) {
                    for (int j = 0; j < lines.size(); j++) {
                        for (int k = 0; k < lines.get(j).getTargetElements().size(); k++) {
                            caculate(centerX + lines.get(j).getResourceX(), centerY + lines.get(j).getResourceY(), lines.get(j).getResourceR(), centerX + lines.get(j).getTargetElements().get(k).getTargetX(), centerY + lines.get(j).getTargetElements().get(k).getTargetY(),
                                    lines.get(j).getTargetElements().get(k).getTargetR() + 3, lines.get(j).getTargetElements().get(k).getText(), lines.get(j).getTargetElements().get(k).getTextColor(), lines.get(j).getTargetElements().get(k).getLineColor(), lines.get(j).getTargetElements().get(k).getTextSize());
                        }
                    }
                }

                if (null != circles && circles.size() > 0) {
                    for (int i = 0; i < circles.size(); i++) {
                        drawCircle(canvas, circles.get(i).getRadius(), centerX + circles.get(i).getX(), centerY + circles.get(i).getY(), circles.get(i).getCircleColor(), circles.get(i).getFillColor(), circles.get(i).getText(), circles.get(i).getTextColor(), circles.get(i).getTextSize());
                    }
                }
                mHolder.unlockCanvasAndPost(canvas);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
    }
    //移动
    private void moveAction(MotionEvent event) {

        synchronized (this) {
            endX = (int) event.getX();
            endY = (int) event.getY();

            if (endX > startX) {
                centerX += (endX - startX) / 2;
            } else {
                centerX -= (startX - endX) / 2;
            }
            if (endY > startY) {
                centerY += (endY - startY) / 2;
            } else {
                centerY -= (startY - endY) / 2;
            }

//            Log.d(TAG, "moveAction " + centerX + "    " + centerY + "  " + Math.abs(endX - startX) + "   " + Math.abs(endY - startY));
            startX = endX;
            startY = endY;
        }
    }

 2、画布缩放,canvas.scale(rate, rate, cX, cY); 基于圆心点缩放。确定好缩放比例就可以了。

 //缩放
    private void zoomAcition(MotionEvent event) {

        synchronized (this) {
            x1 = (int) event.getX(0);
            y1 = (int) event.getY(0);
            x2 = (int) event.getX(1);
            y2 = (int) event.getY(1);
            if (zoomFlag) {
                scaleX = (x1 + x2) / 2;
                scaleY = (y1 + y2) / 2;
                zoomFlag = false;
            }
            Log.d(TAG, "zoomAcition ");
            if (event.getPointerCount() == 2) {
                if (isFirst) {
                    //得到第一次触屏时线段的长度?
                    oldLineDistance = (float) Math.sqrt(Math.pow(event.getX(1) - event.getX(0), 2) + Math.pow(event.getY(1) - event.getY(0), 2));
                    isFirst = false;
                } else {
                    //得到非第1次触屏时线段的长度
                    float newLineDistance = (float) Math.sqrt(Math.pow(event.getX(1) - event.getX(0), 2) + Math.pow(event.getY(1) - event.getY(0), 2));
                    //获取本次的缩放比
                    rate = oldRate * newLineDistance / oldLineDistance;
                }
            }
        }
    }

  3、节点拖动,判断event事件是否发生在节点内,随手指的移动改变圆心的坐标,重新绘制。

 //单点拖动事件
    private void longPressAction(MotionEvent event) {

        if (index == -1) {
            return;
        }
        synchronized (this) {
            Log.d(TAG, "longPressAction ");

            int indexX = circles.get(index).getX(), indexY = circles.get(index).getY();
            endX = (int) event.getX();
            endY = (int) event.getY();

            if (endX > startX) {
                indexX += (endX - startX) / 2;
            } else {
                indexX -= (startX - endX) / 2;
            }
            if (endY > startY) {
                indexY += (endY - startY) / 2;
            } else {
                indexY -= (startY - endY) / 2;
            }

            circles.get(index).setX(indexX);
            circles.get(index).setY(indexY);

            for (int i = 0; i < lines.size(); i++) {
                if (circles.get(index).getId() == lines.get(i).getResouceId()) {//起始点
                    lines.get(i).setResourceX(circles.get(index).getX());
                    lines.get(i).setResourceY(circles.get(index).getY());
                }
            }

            for (int z = 0; z < lines.size(); z++) {
                for (int j = 0; j < lines.get(z).getTargetElements().size(); j++) {
                    if (lines.get(z).getTargetElements().get(j).getTargetId() == circles.get(index).getId()) {//目标点
                        lines.get(z).getTargetElements().get(j).setTargetX(circles.get(index).getX());
                        lines.get(z).getTargetElements().get(j).setTargetY(circles.get(index).getY());
                    }
                }
            }
            startX = endX;
            startY = endY;

        }
    }

在这一步,需要注意的是当画布拖动了并且有缩放的时候,判断Event事件是否在节点内,需要根据缩放比例scale及偏移量去计算。

最后,我把整个RelationShipSurfaceView代码贴出来,没有Demo了

package cn.sunline.embed.terelationview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.util.List;


public class RelationShipSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    private String TAG = "RelationShipSurfaceView";
    private DrawThread mDrawThread;
    private SurfaceHolder mHolder;
    private Paint mPaint;
    private int centerX, centerY, cX, cY;

    //记录两个触屏点的坐标
    private int x1, x2, y1, y2;
    //倍率
    private float rate = 1;
    //记录上次的比例
    private float oldRate = 1;
    //记录第一次触屏时线段的长
    private float oldLineDistance;
    //判定是否头次多指触点屏幕
    private boolean isFirst = true;

    private boolean flag = true;
    private Canvas canvas;
    private int bacColor = Color.WHITE;

    private List circles;
    private List lines;

    public RelationShipSurfaceView(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        mHolder = this.getHolder();
        mHolder.addCallback(this);

        mPaint = new Paint();
        Point point = DensityUtil.getScreenSize(context);
        cX = point.x / 2;
        cY = point.y / 2;
        centerY = point.y / 2;
        centerX = point.x / 2;

        setFocusable(true);
        setKeepScreenOn(true);
        setFocusableInTouchMode(true);
    }

    public void setData(List circle, List line) {
        circles = circle;
        lines = line;
    }

    public void setBacColor(int Color) {
        bacColor = Color;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        flag = true;
        mDrawThread = new DrawThread();
        mDrawThread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        flag = false;
        if (null != mDrawThread) {
            mDrawThread.interrupt();
            mDrawThread = null;
        }
    }

    private TextPaint textPaint = new TextPaint();

    //关系图 圆形
    private void drawCircle(Canvas canvas, int radius, int positionX, int positionY, int circleColor, int fillColor, String text, int textColor, int textSize) {
        mPaint.setColor(circleColor);
        canvas.drawCircle(positionX, positionY, radius, mPaint);
        mPaint.setColor(fillColor);
        canvas.drawCircle(positionX, positionY, radius - 1, mPaint);

        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setColor(textColor);


        mPaint.setTextSize(textSize);

        positionY += 5;
        if (text.length() > 0 && text.length() <= 5) {
            canvas.drawText(text, positionX, positionY, mPaint);
        } else if (text.length() > 5 && text.length() <= 10) {
            canvas.drawText(text.substring(0, 3), positionX, positionY - 25, mPaint);
            canvas.drawText(text.substring(3, text.length()), positionX, positionY, mPaint);
        } else if (text.length() > 10 && text.length() <= 15) {
            canvas.drawText(text.substring(0, 3), positionX, positionY - 25, mPaint);
            canvas.drawText(text.substring(3, 8), positionX, positionY, mPaint);
            canvas.drawText(text.substring(8, text.length()), positionX, positionY + 25, mPaint);
        } else if (text.length() > 15) {
            canvas.drawText(text.substring(0, 3), positionX, positionY - 50, mPaint);
            canvas.drawText(text.substring(3, 8), positionX, positionY - 25, mPaint);
            canvas.drawText(text.substring(8, 14), positionX, positionY, mPaint);
            canvas.drawText(text.substring(14, text.length()), positionX, positionY + 25, mPaint);
        }
        canvas.save();
        mPaint.reset();
    }


    private void caculate(int startX, int startY, int r1, int endX, int endY, int r2, String text, int textColor, int lineColor, int textSize) {

        double h = Math.abs(endY - startY);
        double w = Math.abs(endX - startX);

        double degree = Math.toDegrees(Math.atan(w / h));

//        Log.d(TAG, "CACULATE -- degree " + degree + "  " + (r1 * Math.sin(Math.PI / 180 * 30)));
        int x11 = 0, y11 = 0, x22 = 0, y22 = 0;
        if (startX > endX) {
            x11 = (int) (startX - (r1 * Math.sin(Math.PI / 180 * degree)));
            x22 = (int) (endX + (r2 * Math.sin(Math.PI / 180 * degree)));
        } else {
            x11 = (int) (startX + (r1 * Math.sin(Math.PI / 180 * degree)));
            x22 = (int) (endX - (r2 * Math.sin(Math.PI / 180 * degree)));
        }

        if (startY < endY) {
            y11 = (int) (startY + (r1 * Math.cos(Math.PI / 180 * degree)));
            y22 = (int) (endY - (r2 * Math.cos(Math.PI / 180 * degree)));
        } else {
            y11 = (int) (startY - (r1 * Math.cos(Math.PI / 180 * degree)));
            y22 = (int) (endY + (r2 * Math.cos(Math.PI / 180 * degree)));
        }
        drawAL(canvas, x11, y11, x22 - 3, y22 - 3, text, textColor, lineColor, textSize);
    }

    /**
     * 画箭头
     *
     * @param sx
     * @param sy
     * @param ex
     * @param ey
     */

    Path pathText = new Path();

    public void drawAL(Canvas canvas, int sx, int sy, int ex, int ey, String text, int textColor, int lineColor, int textSize) {
        mPaint.setColor(lineColor);
        mPaint.setStrokeWidth(2);
        double H = 12; // 箭头高度
        double L = 8; // 底边的一半
        int x3 = 0;
        int y3 = 0;
        int x4 = 0;
        int y4 = 0;
        double awrad = Math.atan(L / H); // 箭头角度
        double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度
        double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
        double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
        double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点
        double y_3 = ey - arrXY_1[1];
        double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点
        double y_4 = ey - arrXY_2[1];
        Double X3 = new Double(x_3);
        x3 = X3.intValue();
        Double Y3 = new Double(y_3);
        y3 = Y3.intValue();
        Double X4 = new Double(x_4);
        x4 = X4.intValue();
        Double Y4 = new Double(y_4);
        y4 = Y4.intValue();

//
//        Path triangle = new Path();
//        triangle.moveTo(x3,y3);
//        triangle.lineTo(x4, y4);
//        triangle.lineTo(ex,ey);
//        triangle.
        triangle.close();
//        canvas.drawPath(triangle,mPaint);

//
        canvas.drawLine(x3, y3, ex, ey, mPaint);
        canvas.drawLine(x4, y4, ex, ey, mPaint);
        // 画虚线
        mPaint.setPathEffect(new DashPathEffect(new float[]{4, 4}, 0));
        canvas.drawLine(sx, sy, ex, ey, mPaint);
        mPaint.reset();

        pathText.moveTo(sx, sy);
        pathText.lineTo(ex, ey);
        mPaint.setTextSize(textSize);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setColor(textColor);

        canvas.drawTextOnPath(text, pathText, -4, -4, mPaint);
        mPaint.reset();
        pathText.reset();

    }

    // 计算箭头位置
    public double[] rotateVec(int px, int py, double ang, boolean isChLen, double newLen) {
        double mathstr[] = new double[2];
        // 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
        double vx = px * Math.cos(ang) - py * Math.sin(ang);
        double vy = px * Math.sin(ang) + py * Math.cos(ang);
        if (isChLen) {
            double d = Math.sqrt(vx * vx + vy * vy);
            vx = vx / d * newLen;
            vy = vy / d * newLen;
            mathstr[0] = vx;
            mathstr[1] = vy;
        }
        return mathstr;
    }

    private int scaleX, scaleY;
    private int startX, startY, endX, endY;
    private int mStatus;
    private static final int NONE = 0;// 原始
    private static final int MOVE = 1;// 拖动
    private static final int ZOOM = 2;// 放大
    private static final int LONGPRESS = 3;//长按

    private int index = -1;

    private void transPosition(int x, int y) {

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN://单点
                startX = (int) event.getX();
                startY = (int) event.getY();
                mStatus = MOVE;
                float px = (float) (startX - (1 - rate) * cX);
                float py = (float) (startY - (1 - rate) * cY);

                for (int i = 0; i < circles.size(); i++) {//在某个圆的里面
                    if (px >= ((centerX + circles.get(i).getX() - circles.get(i).getRadius()) * rate) && px <= ((centerX + circles.get(i).getX() + circles.get(i).getRadius()) * rate)) {
                        if (py >= ((centerY + circles.get(i).getY() - circles.get(i).getRadius()) * rate) && py <= ((centerY + circles.get(i).getY() + circles.get(i).getRadius()) * rate)) {
                            mStatus = LONGPRESS;
                            index = i;
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN://缩放
                if (event.getPointerCount() > 1) {
                    mStatus = ZOOM;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mStatus == MOVE) {
                    moveAction(event);
                } else if (mStatus == LONGPRESS) {
                    longPressAction(event);
                } else if (mStatus == ZOOM){
                    if (event.getPointerCount() > 1) {
                        zoomAcition(event);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                isFirst = true;
                oldRate = rate;
                mStatus = NONE;
                zoomFlag = true;
                index = -1;
                break;
        }
        return true;
    }

    class DrawThread extends Thread {
        @Override
        public void run() {
            while (flag) {
                long start = System.currentTimeMillis();
                drawItems();
                long end = System.currentTimeMillis();
                try {
                    if (end - start < 50) {
                        Thread.sleep(50 - (end - start));
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void drawItems() {
        try {
            canvas = mHolder.lockCanvas();
            if (canvas != null) {
                canvas.drawColor(bacColor);
                canvas.save();
                canvas.scale(rate, rate, cX, cY);
                if (null != lines && lines.size() != 0) {
                    for (int j = 0; j < lines.size(); j++) {
                        for (int k = 0; k < lines.get(j).getTargetElements().size(); k++) {
                            caculate(centerX + lines.get(j).getResourceX(), centerY + lines.get(j).getResourceY(), lines.get(j).getResourceR(), centerX + lines.get(j).getTargetElements().get(k).getTargetX(), centerY + lines.get(j).getTargetElements().get(k).getTargetY(),
                                    lines.get(j).getTargetElements().get(k).getTargetR() + 3, lines.get(j).getTargetElements().get(k).getText(), lines.get(j).getTargetElements().get(k).getTextColor(), lines.get(j).getTargetElements().get(k).getLineColor(), lines.get(j).getTargetElements().get(k).getTextSize());
                        }
                    }
                }

                if (null != circles && circles.size() > 0) {
                    for (int i = 0; i < circles.size(); i++) {
                        drawCircle(canvas, circles.get(i).getRadius(), centerX + circles.get(i).getX(), centerY + circles.get(i).getY(), circles.get(i).getCircleColor(), circles.get(i).getFillColor(), circles.get(i).getText(), circles.get(i).getTextColor(), circles.get(i).getTextSize());
                    }
                }
                mHolder.unlockCanvasAndPost(canvas);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
    }
    //移动
    private void moveAction(MotionEvent event) {

        synchronized (this) {
            endX = (int) event.getX();
            endY = (int) event.getY();

            if (endX > startX) {
                centerX += (endX - startX) / 2;
            } else {
                centerX -= (startX - endX) / 2;
            }
            if (endY > startY) {
                centerY += (endY - startY) / 2;
            } else {
                centerY -= (startY - endY) / 2;
            }

//            Log.d(TAG, "moveAction " + centerX + "    " + centerY + "  " + Math.abs(endX - startX) + "   " + Math.abs(endY - startY));
            startX = endX;
            startY = endY;
        }
    }

    private boolean zoomFlag = true;

    //缩放
    private void zoomAcition(MotionEvent event) {

        synchronized (this) {
            x1 = (int) event.getX(0);
            y1 = (int) event.getY(0);
            x2 = (int) event.getX(1);
            y2 = (int) event.getY(1);
            if (zoomFlag) {
                scaleX = (x1 + x2) / 2;
                scaleY = (y1 + y2) / 2;
                zoomFlag = false;
            }
            Log.d(TAG, "zoomAcition ");
            if (event.getPointerCount() == 2) {
                if (isFirst) {
                    //得到第一次触屏时线段的长度?
                    oldLineDistance = (float) Math.sqrt(Math.pow(event.getX(1) - event.getX(0), 2) + Math.pow(event.getY(1) - event.getY(0), 2));
                    isFirst = false;
                } else {
                    //得到非第1次触屏时线段的长度
                    float newLineDistance = (float) Math.sqrt(Math.pow(event.getX(1) - event.getX(0), 2) + Math.pow(event.getY(1) - event.getY(0), 2));
                    //获取本次的缩放比
                    rate = oldRate * newLineDistance / oldLineDistance;
                }
            }
        }
    }

    //单点拖动事件
    private void longPressAction(MotionEvent event) {

        if (index == -1) {
            return;
        }
        synchronized (this) {
            Log.d(TAG, "longPressAction ");

            int indexX = circles.get(index).getX(), indexY = circles.get(index).getY();
            endX = (int) event.getX();
            endY = (int) event.getY();

            if (endX > startX) {
                indexX += (endX - startX) / 2;
            } else {
                indexX -= (startX - endX) / 2;
            }
            if (endY > startY) {
                indexY += (endY - startY) / 2;
            } else {
                indexY -= (startY - endY) / 2;
            }

            circles.get(index).setX(indexX);
            circles.get(index).setY(indexY);

            for (int i = 0; i < lines.size(); i++) {
                if (circles.get(index).getId() == lines.get(i).getResouceId()) {//起始点
                    lines.get(i).setResourceX(circles.get(index).getX());
                    lines.get(i).setResourceY(circles.get(index).getY());
                }
            }

            for (int z = 0; z < lines.size(); z++) {
                for (int j = 0; j < lines.get(z).getTargetElements().size(); j++) {
                    if (lines.get(z).getTargetElements().get(j).getTargetId() == circles.get(index).getId()) {//目标点
                        lines.get(z).getTargetElements().get(j).setTargetX(circles.get(index).getX());
                        lines.get(z).getTargetElements().get(j).setTargetY(circles.get(index).getY());
                    }
                }
            }
            startX = endX;
            startY = endY;

        }
    }


}

 节点model

package cn.sunline.embed.terelationview;

public class CircleModel {

    private int id;//ID
    private int textColor;//字体颜色
    private String text;//文字
    private int x;//圆心x
    private int y;//圆心y
    private int circleColor;//圆环颜色
    private int fillColor;//圆环颜色
    private int radius;//半径
    private int textSize;//圆中字体大小

    public CircleModel() {
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getTextColor() {
        return textColor;
    }

    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getCircleColor() {
        return circleColor;
    }

    public void setCircleColor(int circleColor) {
        this.circleColor = circleColor;
    }

    public int getFillColor() {
        return fillColor;
    }

    public void setFillColor(int fillColor) {
        this.fillColor = fillColor;
    }

    public int getRadius() {
        return radius;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }


    public int getTextSize() {
        return textSize;
    }

    public void setTextSize(int textSize) {
        this.textSize = textSize;
    }
}

linemodel

package cn.sunline.embed.terelationview;

import java.util.List;

public class LineModel {

    private int resouceId;//起始圆id
    private int resourceX;
    private int resourceY;
    private int resourceR;
    private List targetElements;//目标y集合

    public LineModel() {
    }

    public int getResouceId() {
        return resouceId;
    }

    public void setResouceId(int resouceId) {
        this.resouceId = resouceId;
    }

    public int getResourceX() {
        return resourceX;
    }

    public void setResourceX(int resourceX) {
        this.resourceX = resourceX;
    }

    public int getResourceY() {
        return resourceY;
    }

    public void setResourceY(int resourceY) {
        this.resourceY = resourceY;
    }

    public int getResourceR() {
        return resourceR;
    }

    public void setResourceR(int resourceR) {
        this.resourceR = resourceR;
    }

    public List getTargetElements() {
        return targetElements;
    }

    public void setTargetElements(List targetElements) {
        this.targetElements = targetElements;
    }
}

ElementModel

package cn.sunline.embed.terelationview;

import android.graphics.Color;

public class ElementModel {


    private int targetId;
    private int targetX;
    private int targetY;
    private int targetR;
    private String text;
    private int textColor;
    private int lineColor;
    private int textSize;

    public int getTargetId() {
        return targetId;
    }

    public void setTargetId(int targetId) {
        this.targetId = targetId;
    }

    public int getTargetX() {
        return targetX;
    }

    public void setTargetX(int targetX) {
        this.targetX = targetX;
    }

    public int getTargetY() {
        return targetY;
    }

    public void setTargetY(int targetY) {
        this.targetY = targetY;
    }

    public int getTargetR() {
        return targetR;
    }

    public void setTargetR(int targetR) {
        this.targetR = targetR;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public int getTextColor() {
        return textColor;
    }

    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }

    public int getLineColor() {
        return lineColor;
    }

    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
    }

    public int getTextSize() {
        return textSize;
    }

    public void setTextSize(int textSize) {
        this.textSize = textSize;
    }
}

 

你可能感兴趣的:(Android,动态关系图)