• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.github.mikephil.charting.charts;
2 
3 import android.content.Context;
4 import android.graphics.RectF;
5 import android.util.AttributeSet;
6 import android.util.Log;
7 
8 import com.github.mikephil.charting.components.YAxis;
9 import com.github.mikephil.charting.data.BarData;
10 import com.github.mikephil.charting.data.BarEntry;
11 import com.github.mikephil.charting.highlight.BarHighlighter;
12 import com.github.mikephil.charting.highlight.Highlight;
13 import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
14 import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
15 import com.github.mikephil.charting.renderer.BarChartRenderer;
16 
17 /**
18  * Chart that draws bars.
19  *
20  * @author Philipp Jahoda
21  */
22 public class BarChart extends BarLineChartBase<BarData> implements BarDataProvider {
23 
24     /**
25      * flag that indicates whether the highlight should be full-bar oriented, or single-value?
26      */
27     protected boolean mHighlightFullBarEnabled = false;
28 
29     /**
30      * if set to true, all values are drawn above their bars, instead of below their top
31      */
32     private boolean mDrawValueAboveBar = true;
33 
34     /**
35      * if set to true, a grey area is drawn behind each bar that indicates the maximum value
36      */
37     private boolean mDrawBarShadow = false;
38 
39     private boolean mFitBars = false;
40 
BarChart(Context context)41     public BarChart(Context context) {
42         super(context);
43     }
44 
BarChart(Context context, AttributeSet attrs)45     public BarChart(Context context, AttributeSet attrs) {
46         super(context, attrs);
47     }
48 
BarChart(Context context, AttributeSet attrs, int defStyle)49     public BarChart(Context context, AttributeSet attrs, int defStyle) {
50         super(context, attrs, defStyle);
51     }
52 
53     @Override
init()54     protected void init() {
55         super.init();
56 
57         mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler);
58 
59         setHighlighter(new BarHighlighter(this));
60 
61         getXAxis().setSpaceMin(0.5f);
62         getXAxis().setSpaceMax(0.5f);
63     }
64 
65     @Override
calcMinMax()66     protected void calcMinMax() {
67 
68         if (mFitBars) {
69             mXAxis.calculate(mData.getXMin() - mData.getBarWidth() / 2f, mData.getXMax() + mData.getBarWidth() / 2f);
70         } else {
71             mXAxis.calculate(mData.getXMin(), mData.getXMax());
72         }
73 
74         // calculate axis range (min / max) according to provided data
75         mAxisLeft.calculate(mData.getYMin(YAxis.AxisDependency.LEFT), mData.getYMax(YAxis.AxisDependency.LEFT));
76         mAxisRight.calculate(mData.getYMin(YAxis.AxisDependency.RIGHT), mData.getYMax(YAxis.AxisDependency
77                 .RIGHT));
78     }
79 
80     /**
81      * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch
82      * point
83      * inside the BarChart.
84      *
85      * @param x
86      * @param y
87      * @return
88      */
89     @Override
getHighlightByTouchPoint(float x, float y)90     public Highlight getHighlightByTouchPoint(float x, float y) {
91 
92         if (mData == null) {
93             Log.e(LOG_TAG, "Can't select by touch. No data set.");
94             return null;
95         } else {
96             Highlight h = getHighlighter().getHighlight(x, y);
97             if (h == null || !isHighlightFullBarEnabled()) return h;
98 
99             // For isHighlightFullBarEnabled, remove stackIndex
100             return new Highlight(h.getX(), h.getY(),
101                     h.getXPx(), h.getYPx(),
102                     h.getDataSetIndex(), -1, h.getAxis());
103         }
104     }
105 
106     /**
107      * Returns the bounding box of the specified Entry in the specified DataSet. Returns null if the Entry could not be
108      * found in the charts data.  Performance-intensive code should use void getBarBounds(BarEntry, RectF) instead.
109      *
110      * @param e
111      * @return
112      */
getBarBounds(BarEntry e)113     public RectF getBarBounds(BarEntry e) {
114 
115         RectF bounds = new RectF();
116         getBarBounds(e, bounds);
117 
118         return bounds;
119     }
120 
121     /**
122      * The passed outputRect will be assigned the values of the bounding box of the specified Entry in the specified DataSet.
123      * The rect will be assigned Float.MIN_VALUE in all locations if the Entry could not be found in the charts data.
124      *
125      * @param e
126      * @return
127      */
getBarBounds(BarEntry e, RectF outputRect)128     public void getBarBounds(BarEntry e, RectF outputRect) {
129 
130         RectF bounds = outputRect;
131 
132         IBarDataSet set = mData.getDataSetForEntry(e);
133 
134         if (set == null) {
135             bounds.set(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE);
136             return;
137         }
138 
139         float y = e.getY();
140         float x = e.getX();
141 
142         float barWidth = mData.getBarWidth();
143 
144         float left = x - barWidth / 2f;
145         float right = x + barWidth / 2f;
146         float top = y >= 0 ? y : 0;
147         float bottom = y <= 0 ? y : 0;
148 
149         bounds.set(left, top, right, bottom);
150 
151         getTransformer(set.getAxisDependency()).rectValueToPixel(outputRect);
152     }
153 
154     /**
155      * If set to true, all values are drawn above their bars, instead of below their top.
156      *
157      * @param enabled
158      */
setDrawValueAboveBar(boolean enabled)159     public void setDrawValueAboveBar(boolean enabled) {
160         mDrawValueAboveBar = enabled;
161     }
162 
163     /**
164      * returns true if drawing values above bars is enabled, false if not
165      *
166      * @return
167      */
isDrawValueAboveBarEnabled()168     public boolean isDrawValueAboveBarEnabled() {
169         return mDrawValueAboveBar;
170     }
171 
172     /**
173      * If set to true, a grey area is drawn behind each bar that indicates the maximum value. Enabling his will reduce
174      * performance by about 50%.
175      *
176      * @param enabled
177      */
setDrawBarShadow(boolean enabled)178     public void setDrawBarShadow(boolean enabled) {
179         mDrawBarShadow = enabled;
180     }
181 
182     /**
183      * returns true if drawing shadows (maxvalue) for each bar is enabled, false if not
184      *
185      * @return
186      */
isDrawBarShadowEnabled()187     public boolean isDrawBarShadowEnabled() {
188         return mDrawBarShadow;
189     }
190 
191     /**
192      * Set this to true to make the highlight operation full-bar oriented, false to make it highlight single values (relevant
193      * only for stacked). If enabled, highlighting operations will highlight the whole bar, even if only a single stack entry
194      * was tapped.
195      * Default: false
196      *
197      * @param enabled
198      */
setHighlightFullBarEnabled(boolean enabled)199     public void setHighlightFullBarEnabled(boolean enabled) {
200         mHighlightFullBarEnabled = enabled;
201     }
202 
203     /**
204      * @return true the highlight operation is be full-bar oriented, false if single-value
205      */
206     @Override
isHighlightFullBarEnabled()207     public boolean isHighlightFullBarEnabled() {
208         return mHighlightFullBarEnabled;
209     }
210 
211     /**
212      * Highlights the value at the given x-value in the given DataSet. Provide
213      * -1 as the dataSetIndex to undo all highlighting.
214      *
215      * @param x
216      * @param dataSetIndex
217      * @param stackIndex   the index inside the stack - only relevant for stacked entries
218      */
highlightValue(float x, int dataSetIndex, int stackIndex)219     public void highlightValue(float x, int dataSetIndex, int stackIndex) {
220         highlightValue(new Highlight(x, dataSetIndex, stackIndex), false);
221     }
222 
223     @Override
getBarData()224     public BarData getBarData() {
225         return mData;
226     }
227 
228     /**
229      * Adds half of the bar width to each side of the x-axis range in order to allow the bars of the barchart to be
230      * fully displayed.
231      * Default: false
232      *
233      * @param enabled
234      */
setFitBars(boolean enabled)235     public void setFitBars(boolean enabled) {
236         mFitBars = enabled;
237     }
238 
239     /**
240      * Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries.
241      * Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified
242      * by the parameters.
243      * Calls notifyDataSetChanged() afterwards.
244      *
245      * @param fromX      the starting point on the x-axis where the grouping should begin
246      * @param groupSpace the space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f
247      * @param barSpace   the space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f
248      */
groupBars(float fromX, float groupSpace, float barSpace)249     public void groupBars(float fromX, float groupSpace, float barSpace) {
250 
251         if (getBarData() == null) {
252             throw new RuntimeException("You need to set data for the chart before grouping bars.");
253         } else {
254             getBarData().groupBars(fromX, groupSpace, barSpace);
255             notifyDataSetChanged();
256         }
257     }
258 }
259