2016-12-27 24 views
5

バー内のカスタムイメージを追加し、私は下の画像のように、このCombinedChart内部のカスタム描画可能な表示する:言って、MPAndroidChart:私は<a href="https://github.com/PhilJay/MPAndroidChart" rel="nofollow noreferrer">MPAndroidChart</a>を使用しています

バー値がある場合

a bar chart with star images inside the bars

> =目標値を、50、私はバーの中に星のイメージを追加したいと思います。

BarChartをカスタマイズする手助けがありますか?

答えて

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というメソッドを呼び出し、繰り返し処理を各データセットを通過していることがわかりますdrawDataSetに電話してください。 drawDataSetは、アクションが起こっている場所です:影と棒を描いています。これは、画像のような余分を描画するロジックを追加するための適切な場所ですので、のが私たちの画像を描画するメソッドの呼び出しを追加してみましょう。

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

我々は今、データセットを反復処理し、星を描画するメソッドを必要とします画像。テンプレートとして機能する適切なメソッドはdrawValuesです。それをコピーして、テキストではなく画像を描画するように変更しましょう。これを理解するための鍵は、BarBufferの仕組みを見ていることです。 BarBufferは、指定されたエントリのバーのオンスクリーン(ピクセル)座標をj,j + 1,j + 2,j + 3に保持します。

明確にすると、jは左の座標であり、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

関連する問題

 関連する問題