package com.zz.kotlintest.view; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.WindowManager; import com.zz.kotlintest.R; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * @Author xifangzheng * Created by zz on 2017/9/13 17:32. * class explain: 曲线、折线 统计图 * update: upAuthor: explain: */ public class LineGraphicView extends View { String LogTag = this.getClass().getSimpleName(); /** * 公共部分 */ private static final int CIRCLE_SIZE = 6; // 圆点的直径 private boolean isDrawCirclePoints = true; //是否画每个圆点 public ArrayList<ArrayList<Double>> yRawDataLineList; // TODO 自己新增 线的集合 private ArrayList<Paint> paintList; public float pointSpace; // 两个点之间的 x 轴间距 public ArrayList<String> showAlertTextList; public ArrayList<Boolean> isShowBottomRawDatas; public ArrayList<Boolean> isShowTopTextIndexList; private boolean clearView; private String clearAfterShowText = "暂无数据"; public static enum Linestyle { Line, //折线 Curve; //曲线 } private Context mContext; private Paint mPaint; private Resources res; private DisplayMetrics dm; /** * data */ private Linestyle mStyle = Linestyle.Line; public void setStyle(Linestyle mStyle) { this.mStyle = mStyle; } private int canvasHeight; public int canvasWidth; public int bheight = 0; // 表的高度 private int bwidth = 0; // 表的宽度 private int blwidh; // 表的左右边距 private boolean isMeasure = true; /** * Y轴最大值 */ private float maxValue; /** * Y轴间距值 */ private float averageValue; public int marginTop = 40; private int marginBottom = 20; int bottomTextVerticalSpacing = 4; int bottomTextHeight = 24; // 这个可让画布增加底部文字的高度 /** * 曲线上总点数 */ private Point[] mPoints; public ArrayList<Point[]> mPointsLineList; // TODO 新增用来存放所有线的点的集合 /** * 纵坐标值 */ private ArrayList<Double> yRawData; /** * 横坐标值 */ public ArrayList<String> xRawDatas; // 底部显示的文字 private ArrayList<Integer> xList = new ArrayList<Integer>();// 记录每个x的值 private ArrayList<ArrayList<Float>> xListLineList = new ArrayList<>();// 记录每个x的值 // TODO 新增 private float spacingHeight; public boolean isDrawCirclePoints() { return isDrawCirclePoints; } public void setDrawCirclePoints(boolean drawCirclePoints) { isDrawCirclePoints = drawCirclePoints; } public LineGraphicView(Context context) { this(context, null); } public LineGraphicView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; initView(); } private void initView() { this.res = mContext.getResources(); this.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setAntiAlias(true); dm = new DisplayMetrics(); WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); wm.getDefaultDisplay().getMetrics(dm); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.e(LogTag,"onMeasure"); } @Override protected void onFinishInflate() { super.onFinishInflate(); Log.e(LogTag,"onFinishInflate"); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); Log.e(LogTag,"onLayout"); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { Log.e(LogTag,"onSizeChanged"); if (isMeasure) { // this.canvasHeight = getHeight(); // 高度 this.canvasHeight = getHeight() - dip2px(bottomTextHeight) - dip2px(bottomTextVerticalSpacing); // 减的bottomTextHeight是文字的高度 this.canvasWidth = getWidth(); if (bheight == 0) { bheight = (int) (canvasHeight - marginBottom); } blwidh = dip2px(19); this.bwidth = canvasWidth - blwidh * 2; isMeasure = false; // pointSpace = (canvasWidth - blwidh * 2) / (xRawDatas.size() - 1); } if (xRawDatas == null) { return; } pointSpace = Float.valueOf(canvasWidth - blwidh * 2) / (xRawDatas.size() - 1); // Log.e("onSizeChanged打印:", "pointSpace:" + pointSpace + " canvasWidth:" + canvasWidth + " blwidh:" + blwidh + " bwidth:" + bwidth); } @Override public void onDrawForeground(Canvas canvas) { super.onDrawForeground(canvas); Log.e(LogTag,"onDrawForeground"); } @Override protected void onDraw(Canvas canvas) { Log.e(LogTag,"onDraw"); if (clearView) { mPaint.setColor(res.getColor(R.color.color_DefaultDrawLine)); mPaint.setStrokeWidth(dip2px(0)); mPaint.setTextSize(dip2px(15)); mPaint.setStyle(Paint.Style.STROKE); mPaint.setFlags(Gravity.CENTER_HORIZONTAL); canvas.drawText(clearAfterShowText, bwidth / 2 + blwidh - 2 * mPaint.getTextSize(), bheight / 2, mPaint); return; } mPaint.setColor(res.getColor(R.color.color_DefaultDrawLine)); mPaint.setStrokeWidth(dip2px(1)); mPaint.setStyle(Paint.Style.STROKE); if (yRawDataLineList == null) { return; } drawAllXLine(canvas); // 画直线(纵向) // drawAllYLine(canvas); drawAllYLineList(canvas); // 点的操作设置 // mPoints = getPoints(); // 新增 mPointsLineList = getPointsLineList(); // mPaint.setPathEffect(new DashPathEffect(new float[]{20, 20}, 0)); if (mStyle == Linestyle.Curve) { // drawScrollLine(canvas); drawScrollLineList(canvas); } else { // drawLine(canvas); drawLineList(canvas); } mPaint.setStyle(Paint.Style.FILL); if (isDrawCirclePoints) { drawCirclePoints(canvas); } } public ArrayList<String> showAlertTextValuesList = new ArrayList<>(); boolean isShowVerticalLine; // 是否展示触摸后的竖线 boolean isShowCoverRound; // 是否展示覆盖框 private void drawCirclePoints(Canvas canvas) { for (int i = 0; i < mPointsLineList.size(); i++) { for (int j = 0; j < mPointsLineList.get(i).length; j++) { if (paintList.size() == mPointsLineList.size()) { canvas.drawCircle(mPointsLineList.get(i)[j].x, mPointsLineList.get(i)[j].y, CIRCLE_SIZE / 2, paintList.get(i)); } else { canvas.drawCircle(mPointsLineList.get(i)[j].x, mPointsLineList.get(i)[j].y, CIRCLE_SIZE / 2, mPaint); } } } } /** * 画所有横向表格,包括X轴 */ private void drawAllXLine(Canvas canvas) { for (int i = 0; i < spacingHeight + 1; i++) { if (i != 0) { mPaint.setColor(res.getColor(R.color.color_99XLine)); mPaint.setStrokeWidth(2); } else { mPaint.setColor(res.getColor(R.color.color_XLine)); mPaint.setStrokeWidth(dip2px(1)); } canvas.drawLine(blwidh, bheight - (Float.valueOf(bheight) / spacingHeight) * i + marginTop, (canvasWidth - blwidh), bheight - (Float.valueOf(bheight) / spacingHeight) * i + marginTop, mPaint);// Y坐标 drawText(String.valueOf(averageValue * i), blwidh / 2, bheight - (Float.valueOf(bheight) / spacingHeight) * i + marginTop, canvas, R.color.color_LeftText, false); } } /** * 画所有纵向表格,包括Y轴 */ private void drawAllYLineList(Canvas canvas) { xListLineList.clear(); for (int i = 0; i < yRawDataLineList.size(); i++) { ArrayList<Float> xListItem = new ArrayList<>(); for (int j = 0; j < xRawDatas.size(); j++) { mPaint.setColor(res.getColor(R.color.color_YLine)); // Log.e("xlistitem:", "" + (blwidh + (bwidth) / (xRawDatas.size() - 1) * j)); // Log.e("drawAllYLineList打印:", "pointSpace:" + pointSpace + " canvasWidth:" + canvasWidth + " blwidh:" + blwidh + " bwidth:" + bwidth); xListItem.add(blwidh + (Float.valueOf(bwidth)) / (xRawDatas.size() - 1) * j); canvas.drawLine(blwidh + (Float.valueOf(bwidth)) / (xRawDatas.size() - 1) * j, marginTop, blwidh + (Float.valueOf(bwidth)) / (xRawDatas.size() - 1) * j, bheight + marginTop, mPaint); // Log.e("画文本:", xRawDatas.get(j) + "bheight:" + bheight + "canvasWidth:" + canvasWidth); if (i == 0) { drawText(isShowBottomRawDatas.get(j) ? xRawDatas.get(j) : "", blwidh + (Float.valueOf(bwidth)) / (xRawDatas.size() - 1) * j, bheight + dip2px(bottomTextHeight) + dip2px(bottomTextVerticalSpacing), canvas, R.color.color_BottomText, true);// X坐标 } } xListLineList.add(xListItem); } } private void drawScrollLine(Canvas canvas) { Point startp = new Point(); Point endp = new Point(); for (int i = 0; i < mPoints.length - 1; i++) { startp = mPoints[i]; endp = mPoints[i + 1]; int wt = (startp.x + endp.x) / 2; Point p3 = new Point(); Point p4 = new Point(); p3.y = startp.y; p3.x = wt; p4.y = endp.y; p4.x = wt; Path path = new Path(); path.moveTo(startp.x, startp.y); path.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y); canvas.drawPath(path, mPaint); } } Map<Integer, Integer> linesStartIndexMap = new HashMap<>(); Map<Integer, Integer> linesEndIndexMap = new HashMap<>(); private void drawScrollLineList(Canvas canvas) { linesStartIndexMap.clear(); linesEndIndexMap.clear(); for (int i = 0; i < mPointsLineList.size(); i++) { Point startp = new Point(); Point endp = new Point(); for (int j = 0; j < mPointsLineList.get(i).length - 1; j++) { startp = mPointsLineList.get(i)[j]; endp = mPointsLineList.get(i)[j + 1]; if (j == 0 && startp.y >= 0) { linesStartIndexMap.put(i, j); } if (startp.y < 0) { linesStartIndexMap.put(i, j + 1); continue; } linesEndIndexMap.put(i, j + 1); int wt = (startp.x + endp.x) / 2; Point p3 = new Point(); Point p4 = new Point(); p3.y = startp.y; p3.x = wt; p4.y = endp.y; p4.x = wt; Path path = new Path(); path.moveTo(startp.x, startp.y); path.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y); if (paintList.size() == mPointsLineList.size()) { canvas.drawPath(path, paintList.get(i)); } else { canvas.drawPath(path, mPaint); } } } } private void drawLine(Canvas canvas) { Point startp = new Point(); Point endp = new Point(); for (int i = 0; i < mPoints.length - 1; i++) { startp = mPoints[i]; endp = mPoints[i + 1]; canvas.drawLine(startp.x, startp.y, endp.x, endp.y, mPaint); } } private void drawLineList(Canvas canvas) { linesStartIndexMap.clear(); linesEndIndexMap.clear(); for (int i = 0; i < mPointsLineList.size(); i++) { Point startp = new Point(); Point endp = new Point(); for (int j = 0; j < mPointsLineList.get(i).length - 1; j++) { startp = mPointsLineList.get(i)[j]; endp = mPointsLineList.get(i)[j + 1]; if (j == 0 && startp.y >= 0) { linesStartIndexMap.put(i, j); } if (startp.y < 0) { linesStartIndexMap.put(i, j + 1); continue; } linesEndIndexMap.put(i, j + 1); if (paintList.size() == mPointsLineList.size()) { canvas.drawLine(startp.x, startp.y, endp.x, endp.y, paintList.get(i)); } else { canvas.drawLine(startp.x, startp.y, endp.x, endp.y, mPaint); } } } } private void drawText(String text, float x, float y, Canvas canvas, int colorRes, boolean isVerticalText) { drawText(text, x, y, canvas, colorRes, isVerticalText, 12); } private void drawText(String text, float x, float y, Canvas canvas, int colorRes, boolean isVerticalText, int textSizedp) { Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setTextSize(dip2px(textSizedp)); p.setColor(res.getColor(colorRes)); if (isVerticalText) { p.setTextAlign(Paint.Align.CENTER); canvas.drawText(text, x, y, p); } else { p.setTextAlign(Paint.Align.CENTER); canvas.drawText(text, x, y + Float.valueOf(p.getTextSize()) / 3, p); } } private Point[] getPoints() { Point[] points = new Point[yRawData.size()]; for (int i = 0; i < yRawData.size(); i++) { int ph = bheight - (int) (bheight * (yRawData.get(i) / maxValue)); points[i] = new Point(xList.get(i), ph + marginTop); } return points; } public int minTouchXPoint; // 有效触摸点 x轴坐标 起点 public int maxTouchXPoint; // 有效触摸点 x轴坐标 终点 // TODO 下面这个是 获得所有点的方法 /** * 现在需要得到 有效的 x 轴起点和终点 * 在这个方法中计算可得到 * <p> * 目前两条线的起点都为 从0 开始有值时 正常 * 目前其中一条线的起点为 从0 开始有值时 正常 * <p> * 需要处理的是 两条线的起点为 从0 都开始 无值时 603行会报错,因为 startXPointList 集合中无值 因为取值增加目前写的是 每条线 取角标为0(第一个)的加入 */ private ArrayList<Point[]> getPointsLineList() { startTempList.clear(); endTempList.clear(); ArrayList<Point[]> allPointsLineList = new ArrayList<>(); ArrayList<Integer> startXPointList = new ArrayList<>(); ArrayList<Integer> endXPointList = new ArrayList<>(); for (int i = 0; i < yRawDataLineList.size(); i++) { Point[] points = new Point[yRawDataLineList.get(i).size()]; for (int j = 0; j < yRawDataLineList.get(i).size(); j++) { if (yRawDataLineList.get(i).get(j) < 0) { // 为无效点 将不在画线范围 无效点 Y 轴给 -1 值 用于触摸显示 上面方框中的取值 points[j] = new Point(Math.round(xListLineList.get(i).get(j)), -1); } else { int ph = bheight - (int) (bheight * (yRawDataLineList.get(i).get(j) / maxValue)); // Log.e("点坐标:", "x:" + xListLineList.get(i).get(j) + " y:" + ph + marginTop); points[j] = new Point(Math.round(xListLineList.get(i).get(j)), ph + marginTop); a: for (int k = 0; k < yRawDataLineList.get(i).size(); k++) { if (yRawDataLineList.get(i).get(k) >= 0) { startXPointList.add(Math.round(xListLineList.get(i).get(k))); startTempList.put(k, Math.round(xListLineList.get(i).get(k))); break a; } } if (j == yRawDataLineList.get(i).size() - 1) { endXPointList.add(Math.round(xListLineList.get(i).get(j))); endTempList.put(j, Math.round(xListLineList.get(i).get(j))); } } } allPointsLineList.add(points); } minTouchXPoint = Collections.min(startXPointList); maxTouchXPoint = Collections.max(endXPointList); return allPointsLineList; } Map<Integer, Integer> startTempList = new HashMap<>(); Map<Integer, Integer> endTempList = new HashMap<>(); public void setData(ArrayList<ArrayList<Double>> yRawData, ArrayList<String> xBottomRawData, ArrayList<Boolean> isShowBottomRawDatas, ArrayList<Boolean> isShowTopTextIndexList, float maxValue, float averageValue, ArrayList<Paint> paintList, ArrayList<String> showAlertTextList) { this.maxValue = maxValue; this.averageValue = averageValue; this.paintList = paintList; this.showAlertTextList = showAlertTextList; showAlertTextValuesList.clear(); for (int i = 0; i < (showAlertTextList.size() > yRawData.size() ? showAlertTextList.size() : yRawData.size()); i++) { showAlertTextValuesList.add("0"); } // this.mPoints = new Point[yRawData.size()]; ArrayList<Point[]> arrayList = new ArrayList<>(); for (int i = 0; i < yRawData.size(); i++) { arrayList.add(new Point[yRawData.get(i).size()]); } this.mPointsLineList = arrayList; this.xRawDatas = xBottomRawData; this.isShowBottomRawDatas = isShowBottomRawDatas; this.isShowTopTextIndexList = isShowTopTextIndexList; // this.yRawData = yRawData; this.yRawDataLineList = yRawData; this.spacingHeight = maxValue / averageValue; isShowCoverRound = false; isShowVerticalLine = false; // 第一次 初始值都为0 onSizeChanged 方法只会走一次, 走过之后就会计算有值 pointSpace = (canvasWidth - blwidh * 2) / (xRawDatas.size() - 1); // Log.e("setData打印:", "pointSpace:" + pointSpace + " canvasWidth:" + canvasWidth + " blwidh:" + blwidh + " bwidth:" + bwidth); // 重绘一下 postInvalidate(); } public void clearView(boolean isClearView) { this.clearView = isClearView; // 重绘一下 postInvalidate(); } public void clearView(boolean isClearView, String clearAfterShowText) { this.clearView = isClearView; this.clearAfterShowText = clearAfterShowText; // 重绘一下 postInvalidate(); } public void setTotalvalue(int maxValue) { this.maxValue = maxValue; } public void setPjvalue(int averageValue) { this.averageValue = averageValue; } public void setMargint(int marginTop) { this.marginTop = marginTop; } public void setMarginb(int marginBottom) { this.marginBottom = marginBottom; } public void setMstyle(Linestyle mStyle) { this.mStyle = mStyle; } public void setBheight(int bheight) { this.bheight = bheight; } /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ public int dip2px(float dpValue) { return (int) (dpValue * dm.density + 0.5f); } }
package com.zz.kotlintest.view; import android.content.Context; import android.graphics.Paint; import android.graphics.Point; import android.os.Build; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.zz.kotlintest.R; import java.util.ArrayList; import java.util.List; /** * @Author xifangzheng * Created by zz on 2017/10/25 10:35. * class explain: * update: upAuthor: explain: */ public class LineViewRelativeLayout extends RelativeLayout { String LogTag = this.getClass().getSimpleName(); private LineGraphicView lineGraphicView; private TextView moveLine; private TextView tvMoveLineTopText; private float currentTounchX; private LinearLayout llMoveLineCoverRound; private ArrayList<String> showAlertTextList; private ArrayList<Boolean> isShowTopTextIndexList; private ArrayList<String> xBottomRawData; private ArrayList<ArrayList<Double>> yRawDataLineList; private int leftAddWidth; public LineViewRelativeLayout(Context context) { this(context, null); } public LineViewRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); lineGraphicView = new LineGraphicView(context); addView(lineGraphicView); moveLine = new TextView(context); setShowVerticalLine(false); addView(moveLine); tvMoveLineTopText = new TextView(context); setShowVerticalLineTopText(false); addView(tvMoveLineTopText); llMoveLineCoverRound = new LinearLayout(context); addView(llMoveLineCoverRound); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); Log.e(LogTag, "onLayout"); } List<TextView> coverRoundTextViewList; private void layoutAfterDealMoveLineCoverRound() { llMoveLineCoverRound.removeAllViews(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { llMoveLineCoverRound.setBackground(getResources().getDrawable(R.drawable.shape1)); } llMoveLineCoverRound.setOrientation(LinearLayout.VERTICAL); coverRoundTextViewList = new ArrayList<>(); for (int i = 0; i < showAlertTextList.size(); i++) { TextView textView = new TextView(getContext()); textView.setTextSize(12); textView.setTextColor(getResources().getColor(R.color.color_999999)); // textView.setText(showAlertTextList.get(i)); coverRoundTextViewList.add(textView); llMoveLineCoverRound.addView(textView); } RelativeLayout.LayoutParams layoutParams = (LayoutParams) llMoveLineCoverRound.getLayoutParams(); layoutParams.addRule(RelativeLayout.LEFT_OF, moveLine.getId()); layoutParams.width = dip2px(coverRoundWidth); layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; layoutParams.topMargin = dip2px(1); llMoveLineCoverRound.setPadding(dip2px(coverRoundPaddingLeft), dip2px(coverRoundPaddingTop), dip2px(coverRoundPaddingRight), dip2px(coverRoundPaddingBottom)); llMoveLineCoverRound.setLayoutParams(layoutParams); } int coverRoundPaddingLeft = 7; int coverRoundPaddingRight = 2; int coverRoundPaddingTop = 2; int coverRoundPaddingBottom = 2; int coverRoundWidth = 58; private void layoutAfterDealMoveLineTopText() { tvMoveLineTopText.setTextColor(getResources().getColor(R.color.color_999999)); tvMoveLineTopText.setGravity(Gravity.CENTER); tvMoveLineTopText.setTextSize(11); tvMoveLineTopText.setText(""); RelativeLayout.LayoutParams layoutParams = (LayoutParams) tvMoveLineTopText.getLayoutParams(); layoutParams.addRule(RelativeLayout.ABOVE, moveLine.getId()); tvMoveLineTopText.setLayoutParams(layoutParams); } private void layoutAfterDealMoveLine() { moveLine.setBackgroundColor(getResources().getColor(R.color.color_DefaultMoveLine)); moveLine.setWidth(1); RelativeLayout.LayoutParams layoutParams = (LayoutParams) moveLine.getLayoutParams(); layoutParams.topMargin = lineGraphicView.marginTop; moveLine.setLayoutParams(layoutParams); moveLine.setHeight(lineGraphicView.bheight); } boolean isShowVerticalLine = false; boolean isShowVerticalLineTopText = false; boolean isShowMoveLineCoverRound = false; private void setShowMoveLineCoverRound(boolean isShowMoveLineCoverRound) { this.isShowMoveLineCoverRound = isShowMoveLineCoverRound; llMoveLineCoverRound.setVisibility(isShowMoveLineCoverRound ? VISIBLE : INVISIBLE); } private void setShowVerticalLine(boolean isShowVerticalLine) { this.isShowVerticalLine = isShowVerticalLine; moveLine.setVisibility(isShowVerticalLine ? VISIBLE : INVISIBLE); } private void setShowVerticalLineTopText(boolean isShowVerticalLineTopText) { this.isShowVerticalLineTopText = isShowVerticalLineTopText; tvMoveLineTopText.setVisibility(isShowVerticalLineTopText ? VISIBLE : INVISIBLE); } private void showView(boolean isShowVerticalLine, boolean isShowVerticalLineTopText, boolean isShowMoveLineCoverRound) { setShowVerticalLine(isShowVerticalLine); setShowVerticalLineTopText(isShowVerticalLineTopText); setShowMoveLineCoverRound(isShowMoveLineCoverRound); } private void showTouchAfterAll() { showView(true, true, true); } private void hindTouchAfterAll() { showView(false, false, false); } @Override public boolean onTouchEvent(MotionEvent event) { if (yRawDataLineList == null) { return super.onTouchEvent(event); } currentTounchX = Math.round(event.getX()); if (currentTounchX <= lineGraphicView.minTouchXPoint) { currentTounchX = lineGraphicView.minTouchXPoint; } else if (currentTounchX >= lineGraphicView.maxTouchXPoint) { currentTounchX = lineGraphicView.maxTouchXPoint; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: showView(true, true, true); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: // showView(false, false); break; case MotionEvent.ACTION_CANCEL: break; } dealCurrentTouchX(); // return super.onTouchEvent(event); return true; } private int currentIndex = -1; private int preIndex = -1; int valueLength = 2; // 顶部 我的、同行 覆盖区 数字长度判断底值 int everyAddWidth = 7; // 顶部 我的、同行 覆盖区 数字长度每增加一位 增加的宽度 int pointAddWidth = 3; // 顶部 我的、同行 覆盖区 包含小数点时 增加的宽度 private int moveLineSpaceLeftOrRight = 10; public void setMoveLineSpaceLeftOrRight(int moveLineSpaceLeftOrRight) { this.moveLineSpaceLeftOrRight = moveLineSpaceLeftOrRight; } private void dealCurrentTouchX() { Log.e(LogTag, "当前触摸位置 1 : " + currentTounchX); a: for (int i = 0; i < lineGraphicView.mPointsLineList.size(); i++) { Log.e(LogTag, "onLayout x space: " + lineGraphicView.pointSpace); for (int j = 0; j < lineGraphicView.mPointsLineList.get(i).length; j++) { Point point = lineGraphicView.mPointsLineList.get(i)[j]; if (point != null) { Log.e(LogTag, "point[" + i + "][" + j + "]: x = " + point.x + " y = " + point.y); Log.e(LogTag, "当前触摸位置 2 : " + currentTounchX + " 1 " + (Float.valueOf(point.x) + lineGraphicView.pointSpace / 2)); Log.e(LogTag, "当前触摸位置 2 : " + currentTounchX + " 2 " + (Float.valueOf(point.x) - lineGraphicView.pointSpace / 2)); if (currentTounchX <= Float.valueOf(point.x) + lineGraphicView.pointSpace / 2 && currentTounchX >= Float.valueOf(point.x) - lineGraphicView.pointSpace / 2) { currentTounchX = point.x; Log.e(LogTag, "当前触摸位置 3 : " + currentTounchX); currentIndex = j; if (preIndex != currentIndex) { preIndex = currentIndex; tvMoveLineTopText.setText(isShowTopTextIndexList.get(currentIndex) ? xBottomRawData.get(currentIndex) : "");
moveLine.setX(currentTounchX); tvMoveLineTopText.setX(currentTounchX - Float.valueOf(tvMoveLineTopText.getMeasuredWidth() / 2));int maxLength = 0; // int maxLengthIndex = 0; float maxLengthText = 0; for ( int k = 0; k < yRawDataLineList.size(); k++) { // coverRoundTextViewList.get(k).setText(showAlertTextList.get(k) + ": " + yRawDataLineList.get(k).get(currentIndex)); float textNum = 0; if ( currentIndex < yRawDataLineList.get(k).size()) { textNum = Float. valueOf(String. valueOf( yRawDataLineList.get(k).get( currentIndex))); } if (textNum < 0) { textNum = 0; } String textValue = (textNum == Math. round(textNum) ? String. valueOf(Math. round(textNum)) : String. valueOf(textNum)); coverRoundTextViewList.get(k).setText( showAlertTextList.get(k) + ": " + textValue); if (textValue.length() >= maxLength) { // maxLengthIndex = k; maxLengthText = textNum; maxLength = textValue.length(); } } if (maxLength >= valueLength) { float textNum = maxLengthText; String textValue = (textNum == Math. round(textNum) ? String. valueOf(Math. round(textNum)) : String. valueOf(textNum)); leftAddWidth = (textValue.contains( ".") ? dip2px( pointAddWidth) : 0) + (textValue.replace( ".", "").length() - valueLength) * dip2px( everyAddWidth); } RelativeLayout.LayoutParams layoutParams = (LayoutParams) llMoveLineCoverRound.getLayoutParams(); layoutParams. width = dip2px( coverRoundWidth) + leftAddWidth; layoutParams. height = ViewGroup.LayoutParams. WRAP_CONTENT; llMoveLineCoverRound.setLayoutParams(layoutParams); if ( lineGraphicView. canvasWidth - currentTounchX <= llMoveLineCoverRound.getMeasuredWidth() + dip2px( moveLineSpaceLeftOrRight)) { llMoveLineCoverRound.setX( currentTounchX - ( llMoveLineCoverRound.getMeasuredWidth() + dip2px( moveLineSpaceLeftOrRight))); } else { llMoveLineCoverRound.setX( currentTounchX + dip2px( moveLineSpaceLeftOrRight)); } } break a; } } } } } public void setData(ArrayList<ArrayList<Double>> yRawDataLineList, ArrayList<String> xBottomRawData, ArrayList<Boolean> isShowBottomRawDatas, ArrayList<Boolean> isShowTopTextIndexList, float maxValue, float averageValue, ArrayList<Paint> paintList, ArrayList<String> showAlertTextList) { currentIndex = - 1; preIndex = - 1; hindTouchAfterAll(); this. yRawDataLineList = yRawDataLineList; this. xBottomRawData = xBottomRawData; this. isShowTopTextIndexList = isShowTopTextIndexList; this. showAlertTextList = showAlertTextList; lineGraphicView.setData(yRawDataLineList, xBottomRawData, isShowBottomRawDatas, isShowTopTextIndexList, maxValue, averageValue, paintList, showAlertTextList); layoutAfterDealMoveLine(); layoutAfterDealMoveLineTopText(); layoutAfterDealMoveLineCoverRound(); } public void setDrawCirclePoints( boolean drawCirclePoints) { lineGraphicView.setDrawCirclePoints(drawCirclePoints); } public void setStyle(LineGraphicView.Linestyle mStyle) { lineGraphicView.setStyle(mStyle); } public int dip2px( float dpValue) { return lineGraphicView.dip2px(dpValue); }}
shape1:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="3dp" /> <solid android:color="@color/colorWhite" /> <stroke android:width="0.5dp" android:color="@color/color_cccccc" /> </shape>
colors:
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="colorTransparent">#00000000</color> <color name="color_DefaultDrawLine">#ff0000</color> <color name="color_DefaultMoveLine">#cccccc</color> <color name="color_XLine">#e0e0e0</color> <color name="color_99XLine">#99e0e0e0</color> <!--<color name="color_YLine">#cccccc</color>--> <color name="color_YLine">@color/colorTransparent</color> <color name="color_DefaultCoverRoundText">#999999</color> <color name="color_cccccc">#cccccc</color> <color name="color_999999">#999999</color> <color name="color_4c88fc">#4c88fc</color> <color name="color_2bd63f">#2bd63f</color> <color name="colorWhite">#ffffff</color> <color name="colorGreen">#00ff00</color> <color name="colorBlue">#0000ff</color> <color name="colorRed">#ff0000</color> <color name="color_ff3e60">#ff3e60</color> <color name="color_ffa200">#ffa200</color> <color name="color_31cc64">#31cc64</color> <color name="color_3377ff">#3377ff</color> <color name="color_LeftText">@color/colorTransparent</color> <color name="color_BottomText">#424242</color> </resources>
activity: 数据自己看着改
package com.zz.kotlintest; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import com.zz.kotlintest.view.LineGraphicView; import com.zz.kotlintest.view.LineViewRelativeLayout; import java.util.ArrayList; /** * @Author xifangzheng * Created by zz on 2017/9/13 16:30. * class explain: * update: upAuthor: explain: */ public class LineActivity extends AppCompatActivity { private Button btnDataChanges; boolean isDataA = true; // private LineGraphicView lineGraphicView; private LineViewRelativeLayout lineGraphicView; private ArrayList<String> showAlertText; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_line); btnDataChanges = (Button) findViewById(R.id.btnDataChanges); // lineGraphicView = (LineGraphicView) findViewById(R.id.lineGraphicView); lineGraphicView = (LineViewRelativeLayout) findViewById(R.id.lineGraphicView); showAlertText = new ArrayList<>(); showAlertText.add("蓝线"); showAlertText.add("绿线"); // showAlertText.add("红线"); btnDataChanges.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { isDataA = !isDataA; if (isDataA) { lineGraphicView.setStyle(LineGraphicView.Linestyle.Line); dataA(lineGraphicView); } else { lineGraphicView.setStyle(LineGraphicView.Linestyle.Curve); dataB(lineGraphicView); } } }); dataA(lineGraphicView); } private void dataA(LineViewRelativeLayout lineGraphicView) { ArrayList<ArrayList<Double>> lineListA = new ArrayList<>(); ArrayList<Double> yList = new ArrayList(); for (int i = 0; i < 30; i++) { yList.add(12.103 + Math.random() * 10); } // yList.add(5.0); // yList.add(9.0); // yList1.add(5.0); lineListA.add(yList); ArrayList<Double> yList1 = new ArrayList(); for (int i = 0; i < 30; i++) { yList1.add(2.103 + Math.random() * 10); } lineListA.add(yList1); ArrayList<String> xRawDatas = new ArrayList<>(); ArrayList<Boolean> isShowBottomRawDatas = new ArrayList<>(); ArrayList<Boolean> isShowTopTextIndexList = new ArrayList<>(); for (int i = 0; i < 30; i++) { xRawDatas.add(String.valueOf(i + 1)); } for (int i = 0; i < xRawDatas.size(); i++) { isShowBottomRawDatas.add(true); isShowTopTextIndexList.add(true); } // xRawDatas.add("05-26"); // lineGraphicView.setData(yList, xRawDatas, 8, 2); ArrayList<Paint> paintList = new ArrayList<>(); Paint paint1 = new Paint(); paint1.setColor(getResources().getColor(R.color.color_4c88fc)); paint1.setStrokeWidth(lineGraphicView.dip2px(1)); paint1.setStyle(Paint.Style.STROKE); // paint1.setPathEffect(new DashPathEffect(new float[]{20, 20}, 0)); paintList.add(paint1); Paint paint2 = new Paint(); paint2.setColor(getResources().getColor(R.color.color_2bd63f)); paint2.setStrokeWidth(lineGraphicView.dip2px(1)); paint2.setStyle(Paint.Style.STROKE); paint2.setPathEffect(new DashPathEffect(new float[]{10, 10}, 0)); paintList.add(paint2); lineGraphicView.setDrawCirclePoints(false); lineGraphicView.setData(lineListA, xRawDatas, isShowBottomRawDatas, isShowTopTextIndexList, 20, 5, paintList, showAlertText); } private void dataB(LineViewRelativeLayout lineGraphicView) { ArrayList<ArrayList<Double>> lineListB = new ArrayList<>(); ArrayList<Double> yList = new ArrayList<Double>(); for (int i = 0; i < 5; i++) { yList.add(Double.valueOf(Math.round(Math.random() * 1000))); } lineListB.add(yList); ArrayList<Double> yList1 = new ArrayList<Double>(); yList1.add(Double.valueOf(-1)); for (int i = 0; i < 2; i++) { yList1.add(Double.valueOf(Math.round(Math.random() * 1000))); } lineListB.add(yList1); // ArrayList<Double> yList2 = new ArrayList<Double>(); // for (int i = 0; i < 20; i++) { // yList2.add(Double.valueOf(Math.round(Math.random() * 1000))); // } // lineListB.add(yList2); ArrayList<String> xRawDatas = new ArrayList<String>(); ArrayList<Boolean> isShowBottomRawDatas = new ArrayList<>(); ArrayList<Boolean> isShowTopTextIndexList = new ArrayList<>(); for (int i = 0; i < 7; i++) { isShowTopTextIndexList.add(true); xRawDatas.add("" + i); isShowBottomRawDatas.add(true); } ArrayList<Paint> paintList = new ArrayList<>(); Paint paint1 = new Paint(); paint1.setColor(getResources().getColor(R.color.color_4c88fc)); paint1.setStrokeWidth(lineGraphicView.dip2px(1)); paint1.setStyle(Paint.Style.STROKE); paint1.setAntiAlias(true); // paint1.setPathEffect(new DashPathEffect(new float[]{20, 20}, 0)); paintList.add(paint1); Paint paint2 = new Paint(); paint2.setColor(getResources().getColor(R.color.color_2bd63f)); paint2.setStrokeWidth(lineGraphicView.dip2px(1)); paint2.setStyle(Paint.Style.STROKE); paint2.setPathEffect(new DashPathEffect(new float[]{10, 10}, 0)); paint2.setAntiAlias(true); paintList.add(paint2); // Paint paint3 = new Paint(); // paint3.setColor(getResources().getColor(R.color.color_DefaultDrawLine)); // paint3.setStrokeWidth(lineGraphicView.dip2px(1)); // paint3.setStyle(Paint.Style.STROKE); // paint3.setPathEffect(new DashPathEffect(new float[]{10, 10}, 0)); // paint3.setAntiAlias(true); // paintList.add(paint3); lineGraphicView.setDrawCirclePoints(false); lineGraphicView.setData(lineListB, xRawDatas, isShowBottomRawDatas, isShowTopTextIndexList, 1000, 200, paintList, showAlertText); } }
moveLine.setX(currentTounchX); tvMoveLineTopText.setX(currentTounchX - Float.valueOf(tvMoveLineTopText.getMeasuredWidth() / 2));