PhilJay / MPAndroidChart

A powerful 🚀 Android chart view / graph view library, supporting line- bar- pie- radar- bubble- and candlestick charts as well as scaling, panning and animations.
Other
37.64k stars 9.02k forks source link

How to identify bar click event in MPAndroidChart? #3627

Open drd1988on opened 6 years ago

drd1988on commented 6 years ago

It seems the onValueSelected listener is triggered whenever the chart is clicked -- not when a specific bar is selected. I have also noticed this in the sample app for the library (A bar is highlighted even if I click way above it). I would like to limit the click event to the actual bar that is displayed only, this isn't possible at the moment because the listener is even triggered when the white space between bars is tapped

Is there any work around or patch overcome it? I could see that while triggering onValueSelected e.getX() is not returning the exact value when I clicked on outer of bar . For eg When I clicked on the space between first and second graph It is returning the first graph x value

Regards Divya

arunbapi12 commented 6 years ago

As above Divya had mentioned about click event issue for bar chart. It's working for CombinedChart object click event, where clicking on white space onValueSelected is not getting triggered. But in case of BarChart object having the issue.

Even I am not getting proper x & y value for BarChart.

Thanks, Arun

ahmadalibaloch commented 6 years ago

I am also getting same problem for horizontal bar chart. I somehow tried to solve it using setMaxHighlightDistance and setting its value to 2.5f but it is not perfect. With this setting some time the click event works and some time not.

Another problem with bar chart event is that it is fired on tap, it should fire on tap release as it is for the case of Pie Chart. The problem is you can't scroll chart, because you tap to scroll and the event is fired. It should only fire when tap is released.

almic commented 6 years ago

I think this is something that should be addressed, adding to the list.

rustycamper commented 5 years ago

+1 for this one

regas99 commented 5 years ago

The fire on tap issues is easy. Make a one-line change to BarLineChartTouchListener:

case MotionEvent.ACTION_DOWN:
    startAction(event);
    stopDeceleration();
    saveTouchStart(event);
### break -> return true;

The issue of getting clicks outside the bar might be addressed with code in the Activity onValueSelected method. The method is passed the entry and the highlight. If they are not "close enough" you can simply remove the highlight before it is rendered:

    chart.highlightValue(null);

This lets each activity define its own idea of "close enough". Does this address the issue adequately?

Note that my PR #4477 has enhanced support for removing a single highlight if there are more than one:

    chart.getHighlights().remove(highlight)
SIVATEJA97 commented 5 years ago

its working for me when i click on a bar in a barchart the activity is moved to another.But i dont know how to retrieve the value of the bar which I have selected. use the library mpandroidchartlibrary-2-2-4.jar file.

regas99 commented 5 years ago

This is well documented here. Your activity must implement OnChartValueSelectedListener

class MyActivity : DemoBase(), OnChartValueSelectedListener {

    override fun onValueSelected(Entry e, Highlight h) {
        // e is the bar that was highlighted
        // h is the highlight, with the touch point
    }
}
snautiyal commented 5 years ago

This is a bug in MPAndroidChart. It does not differentiate between filled bar and unfilled bar. If we tap on unfilled area (top, bottom, left, right), the OnValueSelected event is fired. I have tried everything but could not get to resolve it. Finally I found a workaround. I used the 'OnChartSingleTap' event of of OnChartGestureListener to capture the current y (getY) position. Then in 'OnValueselected' I compare of h.getYPx<=y. You can do the same for x axis as well. This solved the problem for me.

Thanks, Shan

malwinder-firminiq commented 4 years ago

@snautiyal Is there any proper solution for this issue?

malwinder-s commented 4 years ago

Here is solution to problem: onValueSelected getting called even on unfilled (empty) bar area (top of filled bar area):

    /**
     * Selected Y Index on user tap
     */
    private var selectedYIndex: Float? = null

     override fun onChartSingleTapped(motionEvent: MotionEvent) {
         // Touched chart entry
        val entry: Entry? =
            chartView.getEntryByTouchPoint(motionEvent.x, motionEvent.y)
        selectedYIndex = if (entry != null) {
            //Entry is non-null which means user clicked on bar area (filled or non-filled)
            motionEvent.y
        } else {
            //Entry is null which means user clicked outside of bar area
            null
        }
    }

And then in onValueSelected:

    override fun onValueSelected(e: Entry?, h: Highlight?) {
        //We check for Selected Y Index is non-null (user tapped on non-filled or filled area of bar)
        //Also, we check for selected highlight is non-null and whether user tapped filled area of bar
        if (selectedYIndex != null && h != null && h.yPx <= selectedYIndex!!) {
                  //TODO: User tapped on filled bar area
        } 
    }
CartmanXT commented 1 year ago

Here is solution to problem: onValueSelected getting called even on unfilled (empty) bar area (top of filled bar area):

    /**
     * Selected Y Index on user tap
     */
    private var selectedYIndex: Float? = null

     override fun onChartSingleTapped(motionEvent: MotionEvent) {
         // Touched chart entry
        val entry: Entry? =
            chartView.getEntryByTouchPoint(motionEvent.x, motionEvent.y)
        selectedYIndex = if (entry != null) {
            //Entry is non-null which means user clicked on bar area (filled or non-filled)
            motionEvent.y
        } else {
            //Entry is null which means user clicked outside of bar area
            null
        }
    }

And then in onValueSelected:

    override fun onValueSelected(e: Entry?, h: Highlight?) {
        //We check for Selected Y Index is non-null (user tapped on non-filled or filled area of bar)
        //Also, we check for selected highlight is non-null and whether user tapped filled area of bar
        if (selectedYIndex != null && h != null && h.yPx <= selectedYIndex!!) {
                  //TODO: User tapped on filled bar area
        } 
    }

It's not working

CartmanXT commented 1 year ago

@OverRide public void onChartSingleTapped(MotionEvent me) { x=me.getX(); y=me.getY(); your_bar_char.highlightValue(null); //Turn off highlighting after selected ,Otherwise, you will need to click twice next time } your_bar_chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() { @OverRide public void onValueSelected(Entry e, Highlight h) { if (h.getYPx()<=y&&h.getX()<=x){ //selected bar } else{ //selected the blank area } }

            @Override
            public void onNothingSelected() {

            }
        });