MPAndroidChart 修改柱狀圖高亮效果

MPAndroidChart 默認的選中高亮效果以下:java

只是顏色加深,而後設計想要實現下面這種效果:markdown

相似陰影效果,且顯示的寬度須要增長。框架

1、MPAndroidChart 是否支持

查看該框架對外的接口,發現下面兩個方法:ide

BarDataSet set1 = new BarDataSet(yValues, "");
 set1.setHighLightColor(ContextCompat.getColor(this, R.color.black));
 set1.setHighLightAlpha(40);
複製代碼

只能修改高亮顏色和透明度,沒有辦法修改寬度和高度,沒法達到咱們想要的效果。 沒有辦法,只能先查看源碼是如何實現,而後嘗試去修改了。post

2、查看源碼實現

setHighLightAlpha() 方法入手:this

//BarDataSet.java
    public void setHighLightAlpha(int alpha) {
        mHighLightAlpha = alpha;
    }

    @Override
    public int getHighLightAlpha() {
        return mHighLightAlpha;
    }
複製代碼

查看 getHighLightAlpha() 方法在哪裏調用:spa

//BarChartRenderer.java
    @Override
    public void drawHighlighted(Canvas c, Highlight[] indices) {

        BarData barData = mChart.getBarData();

        for (Highlight high : indices) {

            IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
            ......
            prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);

            setHighlightDrawPos(high, mBarRect);
            //原來高亮背景就是繪製了一個矩形
            c.drawRect(mBarRect, mHighlightPaint);
        }
    }

複製代碼

從源碼中能夠看出,點擊效果就是經過點擊位置,從新繪製一個矩形。 因此重點就是 mBarRect 的賦值。設計

//BarChartRenderer.java
    protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf, Transformer trans) {

        float left = x - barWidthHalf;
        float right = x + barWidthHalf;
        float top = y1;
        float bottom = y2;

        mBarRect.set(left, top, right, bottom);

        trans.rectToPixelPhase(mBarRect, mAnimator.getPhaseY());
    }
複製代碼

能夠看到只要複寫該方法,修改參數,就能夠修改高亮矩形框的寬高。code

3、代碼實現

3.1 重寫 BarChartRenderer 類

查看源碼,發現 BarChartRenderer 的初始化位置,且支持自定義:orm

//BarChart.java
    @Override
    protected void init() {
        super.init();
		//初始化地方
        mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler);

        setHighlighter(new BarHighlighter(this));

        getXAxis().setSpaceMin(0.5f);
        getXAxis().setSpaceMax(0.5f);
    }
    //支持開發者自定義
    public void setRenderer(DataRenderer renderer) {

        if (renderer != null)
            mRenderer = renderer;
    }
複製代碼

自定義 BarChartRenderer

public class TestBarChartRenderer extends BarChartRenderer {

  private Transformer transformer;

  public TestBarChartRenderer( BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
    super(chart, animator, viewPortHandler);
  }

  @Override
  protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf, Transformer trans) {
    transformer = trans;
    //修改高亮效果的高度和寬度,getYChartMax獲取的就是表格的最大值
    super.prepareBarHighlight(x, mChart.getYChartMax(), y2, barWidthHalf + 0.2f, trans);
  }

}

//設置自定義Renderer
barChart.setRenderer(
        new TestBarChartRenderer(barChart, barChart.getAnimator(), barChart.getViewPortHandler()));
//點擊整條數據高亮
barChart.setHighlightFullBarEnabled(true);


複製代碼

3.2 修改全部標記視圖在同一高度問題

上面修改後雖然效果實現了,可是會致使一個問題,點擊數據後,全部的數據的標記視圖都在同一高度:

查看源碼發現:

//BarChartRenderer.java
    @Override
    public void drawHighlighted(Canvas c, Highlight[] indices) {

        BarData barData = mChart.getBarData();

        for (Highlight high : indices) {

            IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
            ......
            prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);
			//修改高亮數據
            setHighlightDrawPos(high, mBarRect);
            //原來高亮背景就是繪製了一個矩形
            c.drawRect(mBarRect, mHighlightPaint);
        }
    }

 protected void setHighlightDrawPos(Highlight high, RectF bar) {
 		//這個位置會影響標記視圖的顯示位置
        high.setDraw(bar.centerX(), bar.top);
    }
複製代碼

因此在 prepareBarHighlight() 方法中修改完數據後,須要在 setHighlightDrawPos() 方法中還原真實的數據。最終代碼以下:

public class TestBarChartRenderer extends BarChartRenderer {

  private Transformer transformer;

  public TestBarChartRenderer( BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
    super(chart, animator, viewPortHandler);
  }

  @Override
  protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf, Transformer trans) {
    transformer = trans;
    //修改高亮背景的高度和寬度
    super.prepareBarHighlight(x, mChart.getYChartMax(), y2, barWidthHalf + 0.2f, trans);
  }

  @Override
  protected void setHighlightDrawPos(Highlight high, RectF bar) {
    if (transformer != null) {
      //還原真實的點擊數據
      float barWidthHalf = mChart.getBarData().getBarWidth() / 2f;
      float x = high.getX();
      RectF rectF = new RectF();
      rectF.set(x - barWidthHalf, high.getY(), x + barWidthHalf, 0f);

      transformer.rectToPixelPhase(rectF, mAnimator.getPhaseY());

      super.setHighlightDrawPos(high, rectF);

    } else {
      super.setHighlightDrawPos(high, bar);
    }
  }
}
複製代碼

柱狀圖的實現能夠參考:

MPAndroidChart實現堆疊柱狀圖

MPAndroidChart 自定義 MarkerView

相關文章
相關標籤/搜索