The default highlight on MPAndroidChart is as follows:

Only the color was deepened, and the design wanted to achieve the following effect:

Similar to shadow effect, and the display width needs to be increased.

First, whether MPAndroidChart is supported

Looking at the external interface of the framework, we find the following two methods:

 BarDataSet set1 = new BarDataSet(yValues, "");
 set1.setHighLightColor(ContextCompat.getColor(this, R.color.black));
 set1.setHighLightAlpha(40);
Copy the code

We can only change the highlight color and transparency, but there is no way to change the width and height to achieve the desired effect. There is no way but to look at the source code is how to implement, and then try to modify it.

Two, view the source code implementation

Start with the setHighLightAlpha() method:

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

    @Override
    public int getHighLightAlpha(a) {
        return mHighLightAlpha;
    }
Copy the code

See where the getHighLightAlpha() method is called:

//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);
            // To highlight the background is to draw a rectanglec.drawRect(mBarRect, mHighlightPaint); }}Copy the code

From the source can be seen, click the effect is by clicking the position, redraw a rectangle. So the point is the assignment of 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());
    }
Copy the code

You can see that you can change the width and height of the highlighted rectangle simply by overwriting the method and modifying the parameters.

Three, code implementation

3.1 Rewrite the BarChartRenderer class

BarChartRenderer initialization location, and support customization:

//BarChart.java
    @Override
    protected void init(a) {
        super.init();
		// Initialize the place
        mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler);

        setHighlighter(new BarHighlighter(this));

        getXAxis().setSpaceMin(0.5 f);
        getXAxis().setSpaceMax(0.5 f);
    }
    // Support developer customization
    public void setRenderer(DataRenderer renderer) {

        if(renderer ! =null)
            mRenderer = renderer;
    }
Copy the code

Custom 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;
    // Change the height and width of the highlight effect. GetYChartMax gets the maximum value of the table
    super.prepareBarHighlight(x, mChart.getYChartMax(), y2, barWidthHalf + 0.2 f, trans); }}// Set the custom Renderer
barChart.setRenderer(
        new TestBarChartRenderer(barChart, barChart.getAnimator(), barChart.getViewPortHandler()));
// Click on the entire data highlight
barChart.setHighlightFullBarEnabled(true);


Copy the code

3.2 Modify all markup views at the same height problem

After clicking on the data, all the labeled views of the data are at the same height:

View the source code found:

//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);
			// Modify the highlighted data
            setHighlightDrawPos(high, mBarRect);
            // To highlight the background is to draw a rectanglec.drawRect(mBarRect, mHighlightPaint); }}protected void setHighlightDrawPos(Highlight high, RectF bar) {
 		// This position will affect the display position of the tag view
        high.setDraw(bar.centerX(), bar.top);
    }
Copy the code

So after modifying the data in prepareBarHighlight(), you need to restore the real data in setHighlightDrawPos(). The final code is as follows:

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;
    // Modify the height and width of the highlighted background
    super.prepareBarHighlight(x, mChart.getYChartMax(), y2, barWidthHalf + 0.2 f, trans);
  }

  @Override
  protected void setHighlightDrawPos(Highlight high, RectF bar) {
    if(transformer ! =null) {
      // Restore the real click data
      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); }}}Copy the code

The implementation of the bar chart can refer to:

MPAndroidChart implements stacked bar charts

MPAndroidChart custom MarkerView