ChartsOrg / Charts

Beautiful charts for iOS/tvOS/OSX! The Apple side of the crossplatform MPAndroidChart.
Apache License 2.0
27.61k stars 6k forks source link

Show summarized Value of Stacked (horizontal) BarChart #526

Open sPooKee opened 9 years ago

sPooKee commented 9 years ago

Hy,

is it possible to show (only) the summarized value of a stacked (horizontal) BarCahrt, because the are hard to read for example if the second stack is very small. The labels are overlapping.

Thanks so far.

liuxuan30 commented 9 years ago

I looked at the code, seems we don't support this yet, but it should be easy to do.

Stacked bar data entry has some properties and methods to calculate the sum. and in drawValues, there you can add a switch to render the sum value just like normal bars do.

What you should watch out is, for stacked bars, there is postive and negative values, so the sum may be weird depending on what your chart wants to present the x axis.

@danielgindi , consider this as a feature? To me, if we are going to add it, we may want to support only show negative/positive sums as well.

josephrussell commented 7 years ago

Hello, thanks for the great project. I'm coming across this need as well. I'm attempting to display a label the with sum of all stacks for the the bar and not display the individual labels.

I attempted a workaround with an IValueFormatter and only display the sum on the last stack but I didn't see a way to know whether I was in the last stack from the interface method.

func stringForValue(_ value: Double,
                        entry: ChartDataEntry,
                        dataSetIndex: Int,
                        viewPortHandler: ViewPortHandler?) -> String

Seems like I needed k value from where it was called in HorizontalBarChartRenderer to be able to check if it was the last stack.

let val = vals[k]
let valueText = formatter.stringForValue(
    val,
    entry: e,
    dataSetIndex: dataSetIndex,
    viewPortHandler: viewPortHandler)

Another switch like you mention may be better. Any update since the last comment?

guillaumejounel commented 5 years ago

Hi there,

I've just achieved this by creating a CustomHorizontalBarChartRenderer inheriting from HorizontalBarChartRenderer. Then I've overridden func drawValues(context: CGContext) as suggested by @josephrussell who was actually really close.

Here is the interesting piece of code:

for k in 0 ..< transformed.count {
    let val = vals[k]
    let valueText = formatter.stringForValue(
        val,
        entry: e,
        dataSetIndex: dataSetIndex,
        viewPortHandler: viewPortHandler)
    ...
    let x = transformed[transformed.count-1].x + (drawBelow ? negOffset : posOffset)
    ...
}

Here, drawValues is executed for each entry e, and for each entry, every value k is displayed. So, if we want to display only the summary value, we can just get rid of that loop and compute the summary value for each entry. Then, we can display the value at the beginning of the bar by modifying x (or y if you have a vertical stacked bar):

let sumVals = vals.reduce(0, +)
let valueText = formatter.stringForValue(
    sumVals,
    entry: e,
    dataSetIndex: dataSetIndex,
    viewPortHandler: viewPortHandler)
...
let x = rect.origin.x + (drawBelow ? negOffset : posOffset)
...

You can also append that code out of the loop if you'd like to get both all values and summary value.

Hope that helps!

sreerajPR commented 3 years ago

I had a similar requirement to show the summarized value for a Stacked Bar Chart. I could solve it by assigning an IValueFormatter to BarChartData Please find my solution in this SO Answer