2016-12-27 66 views

回答

4

要獲得我們酒吧內的星形圖像,我們需要創建一個自定義渲染器。因爲我們的條形圖使用BarChartRenderer我們將繼承這個第一和添加參數爲我們的形象:

public class ImageBarChartRenderer extends BarChartRenderer { 

    private final Bitmap barImage; 

    public ImageBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler, Bitmap barImage) { 
     super(chart, animator, viewPortHandler); 
     this.barImage = barImage; 
    } 

如果我們檢查源BarChartRenderer我們可以看到,它調用調用的方法drawData,然後遍歷每個數據集和請致電drawDataSetdrawDataSet是動作發生的地方:它正在繪製陰影和酒吧。這是一個合適的地方加入邏輯繪製圖像等額外的,所以讓我們添加一個調用一個方法有引起我們的圖片:

@Override 
    protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { 
     super.drawDataSet(c, dataSet, index); 
     drawBarImages(c, dataSet, index); 
    } 

我們現在需要的是將通過DataSet迭代並繪製星的方法圖片。一個適當的方法將作爲模板drawValues所以讓我們複製並更改它,以便繪製圖像而不是文本。理解這一點的關鍵是看BarBuffer是如何工作的。 BarBuffer保存給定條目的條形屏幕(像素)座標,格式爲j,j + 1,j + 2,j + 3

爲了澄清,j是左x座標,j + 1是最高y座標等等,通過右邊x座標j + 3。我們將提取這些變量,使其更易於理解:

protected void drawBarImages(Canvas c, IBarDataSet dataSet, int index) { 
     BarBuffer buffer = mBarBuffers[index]; 

     float left; //avoid allocation inside loop 
     float right; 
     float top; 
     float bottom; 

     for (int j = 0; j < buffer.buffer.length * mAnimator.getPhaseX(); j += 4) { 
      left = buffer.buffer[j]; 
      right = buffer.buffer[j + 2]; 
      top = buffer.buffer[j + 1]; 
      bottom = buffer.buffer[j + 3]; 

      float x = (left + right)/2f; 

      if (!mViewPortHandler.isInBoundsRight(x)) 
       break; 

      if (!mViewPortHandler.isInBoundsY(top) 
        || !mViewPortHandler.isInBoundsLeft(x)) 
       continue; 

      BarEntry entry = dataSet.getEntryForIndex(j/4); 
      float val = entry.getY(); 

      if (val > 50) { 
       drawStar(c, barImage, x, top); 
      } 
     } 
    } 

下面是如何消費的渲染:

Bitmap starBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.star); 
    mChart.setRenderer(new ImageBarChartRenderer(mChart, mChart.getAnimator(), mChart.getViewPortHandler(), starBitmap)); 

渲染器的最後一步是添加邏輯來縮放位圖和正確定位。下面是自定義渲染的最終證明的概念:

package com.xxmassdeveloper.mpchartexample; 

import android.graphics.Bitmap; 
import android.graphics.Canvas; 

import com.github.mikephil.charting.animation.ChartAnimator; 
import com.github.mikephil.charting.buffer.BarBuffer; 
import com.github.mikephil.charting.data.BarEntry; 
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; 
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; 
import com.github.mikephil.charting.renderer.BarChartRenderer; 
import com.github.mikephil.charting.utils.ViewPortHandler; 

/** 
* Created by David on 29/12/2016. 
*/ 

public class ImageBarChartRenderer extends BarChartRenderer { 

    private final Bitmap barImage; 

    public ImageBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler, Bitmap barImage) { 
     super(chart, animator, viewPortHandler); 
     this.barImage = barImage; 
    } 

    @Override 
    public void drawData(Canvas c) { 
     super.drawData(c); 
    } 

    @Override 
    protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { 
     super.drawDataSet(c, dataSet, index); 
     drawBarImages(c, dataSet, index); 
    } 

    protected void drawBarImages(Canvas c, IBarDataSet dataSet, int index) { 
     BarBuffer buffer = mBarBuffers[index]; 

     float left; //avoid allocation inside loop 
     float right; 
     float top; 
     float bottom; 

     final Bitmap scaledBarImage = scaleBarImage(buffer); 

     int starWidth = scaledBarImage.getWidth(); 
     int starOffset = starWidth/2; 

     for (int j = 0; j < buffer.buffer.length * mAnimator.getPhaseX(); j += 4) { 
      left = buffer.buffer[j]; 
      right = buffer.buffer[j + 2]; 
      top = buffer.buffer[j + 1]; 
      bottom = buffer.buffer[j + 3]; 

      float x = (left + right)/2f; 

      if (!mViewPortHandler.isInBoundsRight(x)) 
       break; 

      if (!mViewPortHandler.isInBoundsY(top) 
        || !mViewPortHandler.isInBoundsLeft(x)) 
       continue; 

      BarEntry entry = dataSet.getEntryForIndex(j/4); 
      float val = entry.getY(); 

      if (val > 50) { 
       drawImage(c, scaledBarImage, x - starOffset, top); 
      } 
     } 
    } 

    private Bitmap scaleBarImage(BarBuffer buffer) { 
     float firstLeft = buffer.buffer[0]; 
     float firstRight = buffer.buffer[2]; 
     int firstWidth = (int) Math.ceil(firstRight - firstLeft); 
     return Bitmap.createScaledBitmap(barImage, firstWidth, firstWidth, false); 
    } 

    protected void drawImage(Canvas c, Bitmap image, float x, float y) { 
     if (image != null) { 
      c.drawBitmap(image, x, y, null); 
     } 
    } 
} 

這裏有一個屏幕截圖 - 你可以看到,超過50值有星:

bar chart with custom image inside bars

+0

感謝答案。 –

+0

不客氣。 –

+0

你在這裏使用什麼版本的mpandroid圖表? – Amalo