欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android?RecyclerBarChart繪制使用教程

 更新時(shí)間:2022年12月09日 09:06:36   作者:cxy107750  
這篇文章主要為大家介紹了Android?RecyclerBarChart繪制使用教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

上篇介紹了幾種圖表的公共組件X、Y軸、背景Board的繪制。這章節(jié)介紹柱狀圖表的繪制,相對(duì)其它圖表而言簡(jiǎn)單一些,這里主要介紹圖表主體的繪制,以及高亮選中的其中一個(gè)的選中框的繪制的相關(guān)邏輯。對(duì)每個(gè)ItemView中的ItemDecoration上進(jìn)行onDraw的操作,需要將View跟Model進(jìn)行綁定在一起,單個(gè)柱子的一些屬性可以通過(guò)Model來(lái)獲取,整體的一些繪制的輔助信息color、size等可以通過(guò)Attribute類設(shè)置。View 跟Model的綁定不止是BarChart圖表,所以的都是一樣的。

以下是在BarAdapter中的onBindViewHolder方法中進(jìn)行關(guān)聯(lián)二者:

根據(jù)之前的介紹繪制的邏輯都在ItemDecoration里,我們看下BarChartItemDecoration的onDrawOver, 對(duì)于X、Y軸、Board的繪制其實(shí)可以沉淀到BaseItemDecoration中的,這里直接寫了。

這里我們著重看下drawBarChart、drawHighLight、drawBarChartValues的繪制。

1.drawBarChart

繪制柱狀圖的主體,通過(guò)ItemView拿到對(duì)應(yīng)的Entry對(duì)象,根據(jù)Entry中的Y值進(jìn)行Y坐標(biāo)值的轉(zhuǎn)化,然后繪制單個(gè)Item RectF的繪制。

//繪制柱狀圖, mYAxis這個(gè)坐標(biāo)會(huì)實(shí)時(shí)變動(dòng),所以通過(guò) BarChartItemDecoration 傳過(guò)來(lái)的精確值。
    final public void drawBarChart(final Canvas canvas, @NonNull final RecyclerView parent, final YAxis mYAxis) {
        final float parentRight = parent.getWidth() - parent.getPaddingRight();
        final float parentLeft = parent.getPaddingLeft();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            BarEntry barChart = (BarEntry) child.getTag();
            RectF rectF = ChartComputeUtil.getBarChartRectF(child, parent, mYAxis, mBarChartAttrs, barChart);
            drawChart(canvas, rectF, parentLeft, parentRight);
        }
    }

繪制的邏輯具體在 drawChart(canvas, rectF, parentLeft, parentRight) 的方法里,這里我們先看看 RectF 的計(jì)算,工具類ChartComputeUtil.getBarChartRectF() 的方法。

public static <T extends BarEntry, V extends BaseYAxis, E extends BaseChartAttrs> RectF getBarChartRectF(View child, final RecyclerView parent, V mYAxis, E chartAttrs, T barEntry) {
        final RectF rectF = new RectF();
        float contentBottom = parent.getHeight() - parent.getPaddingBottom() - chartAttrs.contentPaddingBottom;
        float realYAxisLabelHeight = contentBottom - parent.getPaddingTop() - chartAttrs.contentPaddingTop;
        float width = child.getWidth();
        float barSpaceWidth = width * chartAttrs.barSpace;
        float barChartWidth = width - barSpaceWidth;//柱子的寬度
        final float left = child.getLeft() + barSpaceWidth / 2;
        final float right = left + barChartWidth;
        float height = barEntry.getY() / mYAxis.getAxisMaximum() * realYAxisLabelHeight;
        if (chartAttrs.yAxisReverse && barEntry.getY() > 0) {
            float valueTemp = mYAxis.getAxisMaximum() - barEntry.getY();
            height = valueTemp / mYAxis.getAxisMaximum() * realYAxisLabelHeight;
        }
        final float top = Math.max(contentBottom - height, parent.getPaddingTop());
        rectF.set(left, top, right, contentBottom);
        return rectF;
    }

柱子RectF 的計(jì)算,Width根據(jù) itemView的width 以及每個(gè)ItemView的空余所占比例的一個(gè)ChartAttrs中的參數(shù)

barSpace計(jì)算得來(lái),算出RectF的 left、right; height 的計(jì)算,涉及到Entry 的Y值以及YAxis 當(dāng)前顯示情況下的getAxisMaximum(),這里默認(rèn)了Minmum為0,業(yè)務(wù)邏輯的Y值比例轉(zhuǎn)化成 屏幕Pixel對(duì)應(yīng)的高度,然后根據(jù)ItemView的top、bottom計(jì)算得到 RectF的 top, bottom. (這里的計(jì)算,到時(shí)候其它圖表高度也可以用)。

獲取到 單個(gè)ItemView 中BarChart 所占的RectF確定后,畫RectF就比較簡(jiǎn)單了,稍微有點(diǎn)難點(diǎn)的是處理一下邊界的問(wèn)題,邊界問(wèn)題,柱狀圖相比線形圖等簡(jiǎn)單一些,處于邊界的柱子繪制的顏色不一樣,交給用戶mBarChartAttrs.chartEdgeColor傳color值,這里默認(rèn)設(shè)置的是Gray。

private void drawChart(Canvas canvas, RectF rectF, float parentLeft, float parentRight) {
    float radius = (rectF.right - rectF.left) *mBarChartAttrs.barChartRoundRectRadiusRatio;
    // 浮點(diǎn)數(shù)的 == 比較需要注意
    if (DecimalUtil.smallOrEquals(rectF.right, parentLeft)) {
      //continue 會(huì)閃,原因是end == parentLeft 沒有過(guò)濾掉,顯示出來(lái)柱狀圖了。
      return;
    } else if (rectF.left < parentLeft && rectF.right > parentLeft) {
      //左邊部分滑入的時(shí)候,處理柱狀圖的顯示
      rectF.left = parentLeft;
      Path path = CanvasUtil.createRectRoundPath(rectF, radius, RoundRectType.TYPE_RIGHT);
      mBarChartPaint.setColor(mBarChartAttrs.chartEdgeColor);
      canvas.drawPath(path, mBarChartPaint);
    } else if (DecimalUtil.bigOrEquals(rectF.left, parentLeft) && DecimalUtil.smallOrEquals(rectF.right, parentRight)) {
      //中間的; 浮點(diǎn)數(shù)的 == 比較需要注意
      mBarChartPaint.setColor(mBarChartAttrs.chartColor);
      Path path = CanvasUtil.createRectRoundPath(rectF, radius);
      canvas.drawPath(path, mBarChartPaint);
    } else if (DecimalUtil.smallOrEquals(rectF.left, parentRight) && 
               rectF.right > parentRight) {
      //右邊部分滑出的時(shí)候,處理柱狀圖,文字的顯示
      float distance = (parentRight - rectF.left);
      rectF.right = rectF.left + distance;
      Path path = CanvasUtil.createRectRoundPath(rectF, radius, RoundRectType.TYPE_LEFT);
            mBarChartPaint.setColor(mBarChartAttrs.chartEdgeColor);
            canvas.drawPath(path, mBarChartPaint);
        }
   }

下面是個(gè)步數(shù)的周視圖:

2.drawHighLight

首先看下這里高亮具體是如何顯示的,直觀的看些圖:

當(dāng)前的RecyclerView的getChildCount內(nèi)每個(gè)ItemView對(duì)應(yīng)的Entry,設(shè)定了一個(gè) selected 的字段來(lái)確定顯示高亮,至于該字段的值的設(shè)定及變化,后續(xù)章節(jié)會(huì)介紹,這里假定已經(jīng)確定了當(dāng)前的某一個(gè)ItemView的Entry的selected是選中狀態(tài)的,它有可能在中間,或者在邊界需要處理邊界繪制的問(wèn)題,這里分畫頂部的矩形框及drawTextValue值,底部繪制drawLine(這個(gè)不存在繪制的邊界問(wèn)題)

//繪制選中時(shí) highLight 標(biāo)線及浮框。
public <E extends BaseYAxis> void drawHighLight(Canvas canvas, @NonNull RecyclerView parent, E yAxis) {
  if (mBarChartAttrs.enableValueMark) {
    int childCount = parent.getChildCount();
    View child;
    for (int i = 0; i < childCount; i++) {
      child = parent.getChildAt(i);
      T entry = (T) child.getTag();
      RectF rectF = ChartComputeUtil.getBarChartRectF(child, parent, yAxis, mBarChartAttrs, entry);
      float width = child.getWidth();
      float childCenter = child.getLeft() + width / 2;
      String valueStr = mHighLightValueFormatter.getBarLabel(entry);
      if (entry.isSelected() && !TextUtils.isEmpty(valueStr)) {
        int chartColor = getChartColor(entry);
        float rectHeight = drawHighLightValue(canvas, valueStr, childCenter, parent, chartColor);//繪制頂部的poupWindow,高亮矩形框及drawText
        float[] points = new float[]{childCenter, rectF.top, childCenter, rectHeight};
        drawHighLightLine(canvas, points, chartColor);//繪制底部的Line
      }
    }
  }
}

以上中 drawHighLightValue 中, 包含了繪制矩形、drawText兩項(xiàng)具體的內(nèi)容:

//繪制柱狀圖選中浮框
protected float drawHighLightValue(Canvas canvas, String valueStr, float childCenter,
                                   RecyclerView parent, int barChartColor) {
  float parentTop = parent.getPaddingTop();
  float contentRight = parent.getWidth() - parent.getPaddingRight();
  float contentLeft = parent.getPaddingLeft();
  String[] strings = valueStr.split(DefaultHighLightMarkValueFormatter.CONNECT_STR);
  float leftEdgeDistance = Math.abs(childCenter - contentLeft);
  float rightEdgeDistance = Math.abs(contentRight - childCenter);
  float leftPadding = DisplayUtil.dip2px(8);
  float rightPadding = DisplayUtil.dip2px(8);
  float centerPadding = DisplayUtil.dip2px(16);
  float rectBottom = parentTop;
  float txtTopPadding = DisplayUtil.dip2px(8);
  String leftStr = strings[0];
  String rightStr = strings[1];
  float txtLeftWidth = mHighLightValuePaint.measureText(leftStr);
  float txtRightWidth = mHighLightValuePaint.measureText(rightStr);
  float rectFHeight = TextUtil.getTxtHeight1(mHighLightValuePaint) + txtTopPadding * 2;
  float txtWidth = txtLeftWidth + txtRightWidth + leftPadding +
    rightPadding + centerPadding;
  float edgeDistance = txtWidth / 2.0f;
  float rectTop = parentTop - rectFHeight;
  //繪制RectF
  RectF rectF = new RectF();
  mBarChartPaint.setColor(barChartColor);
  if (leftEdgeDistance <= edgeDistance) {//矩形框靠左對(duì)齊
    rectF.set(contentLeft, rectTop, contentLeft + txtWidth, rectBottom);
    float radius = DisplayUtil.dip2px(8);
    canvas.drawRoundRect(rectF, radius, radius, mBarChartPaint);
  } else if (rightEdgeDistance <= edgeDistance) {//矩形框靠右對(duì)齊
    rectF.set(contentRight - txtWidth, rectTop, contentRight, rectBottom);
    float radius = DisplayUtil.dip2px(8);
    canvas.drawRoundRect(rectF, radius, radius, mBarChartPaint);
  } else {//居中對(duì)齊。
    rectF.set(childCenter - edgeDistance, rectTop, childCenter + edgeDistance, rectBottom);
    float radius = DisplayUtil.dip2px(8);
    canvas.drawRoundRect(rectF, radius, radius, mBarChartPaint);
  }
  //繪文字
  RectF leftRectF = new RectF(rectF.left + leftPadding, rectTop + txtTopPadding,
                              rectF.left + leftPadding + 
                              txtLeftWidth, rectTop + txtTopPadding + rectFHeight);
  mHighLightValuePaint.setTextAlign(Paint.Align.LEFT);
  Paint.FontMetrics fontMetrics = mHighLightValuePaint.getFontMetrics();
  float top = fontMetrics.top;//為基線到字體上邊框的距離,即上圖中的top
  float bottom = fontMetrics.bottom;//為基線到字體下邊框的距離,即上圖中的bottom
  int baseLineY = (int) (leftRectF.centerY() + (top + bottom) / 2);//基線中間點(diǎn)的y軸計(jì)算公式
  canvas.drawText(leftStr, rectF.left + leftPadding, baseLineY, mHighLightValuePaint);
  float dividerLineStartX = rectF.left + leftPadding + txtLeftWidth + centerPadding / 2.0f;
  float dividerLineStartY = rectTop + DisplayUtil.dip2px(10);
  float dividerLineEndX = dividerLineStartX;
  float dividerLineEndY = rectBottom - DisplayUtil.dip2px(10);
  float[] lines = new float[]{dividerLineStartX, dividerLineStartY, 
                              dividerLineEndX, dividerLineEndY};
  canvas.drawLines(lines, mHighLightValuePaint);
  float rightRectFStart = rectF.left + leftPadding + txtLeftWidth + centerPadding;
  RectF rightRectF = new RectF(rightRectFStart, rectTop + txtTopPadding,
                               rectF.right - rightPadding, rectBottom - txtTopPadding);
  canvas.drawText(rightStr, rightRectF.left, baseLineY, mHighLightValuePaint);
  return rectFHeight;
}

具體的文案繪制內(nèi)容 valueStr 從 ValueFormatter里獲取,我這里需要拆分一下ValueStr,然后繪制leftStr, rightStr這里相當(dāng)于各個(gè)項(xiàng)目自己的需求。

以上就是Android RecyclerBarChart繪制使用教程的詳細(xì)內(nèi)容,更多關(guān)于Android RecyclerBarChart繪制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論