MPAndroidChart icon indicating copy to clipboard operation
MPAndroidChart copied to clipboard

Display highlited Entry values on the axis

Open MGaetan89 opened this issue 10 years ago • 9 comments

I started to use this library for my project and here is a first suggestion/question (depending on whether it is already possible or not).

When I select a point (Entry) on my LineChart, I would like its values (x & y) to be display on the x axis and y axis respectively. Is this possible? If not, is it easy to implement?

Thanks for this awesome library!

MGaetan89 avatar Nov 18 '14 21:11 MGaetan89

That's actually a very good idea. I will consider to add this in a future update. In my opinion it should be possible to implement such a feature with moderate effort.

PhilJay avatar Nov 18 '14 22:11 PhilJay

Seems like this is similar to the feature implemented in this pull request: https://github.com/PhilJay/MPAndroidChart/pull/478

I couldn't find the commits, but I assume the Y-axis drawing eventually got merged in. If so it shouldn't be hard to get similar functionality on the X-axis I'd imagine.

clay-to-n avatar Jul 01 '15 22:07 clay-to-n

+1, this would be great!

Enteleform avatar Jul 22 '15 18:07 Enteleform

Is this implemented?

Drakot avatar Jun 30 '16 11:06 Drakot

+1

xdnan7 avatar Jul 22 '16 07:07 xdnan7

[Update: the behavior of the axis highlight has changed in the final version - PR #4477. The axis now draw a recttangle and text at the highlighted value. See the PR for details.]

I am pretty close to completing work on this. The proposed functionality is documented below, and an example screen shot is provided. Please provide feedback and suggestions for changes / improvements.

Sample screen shot.

Maps the largest cities in California. Two points on the right log log axis have been touched, and only cities whose populations are between those values are rendered. The city of Bakersfield has also been highlighted.

screenshot2

Proposed wiki page:

This section focuses on the topic of highlighting entries in the chart, both via tap-gesture and programmatically based on Pull Request ###.

Highlightable Items

Both data vales and individual axes can be highlighted.

Enabling / Disabling highlighting

For The Chart
  • setHighlightPerDragEnabled(boolean enabled): Set this to true on your Chart to allow highlighting per dragging over the chart surface when it is fully zoomed out. Default: true
  • setHighlightPerTapEnabled(boolean enabled): Set this to false on your Chart to prevent values from being highlighted by tap gesture. Values can still be highlighted via drag or programmatically. Default: true
  • setMaxHighlightDistance(float distanceDp): Sets the maximum highlight distance in dp. Taps on the chart further away from an entry than that distance will not trigger a highlight. Default: 500dp
For the DataSets

Highlighting can be configured for individual DataSet objects:

  dataSet.setHighlightEnabled(true); // allow highlighting for DataSet

  // set this to false to disable the drawing of highlight indicator (lines)
  dataSet.setDrawHighlightIndicators(true); 
  dataSet.setHighlightColor(Color.BLACK); // color for highlight indicator
  // and more...
For the axes

Highlighting can be configured for each axis:

axis.setHighlightEnabled(true); // allow highlighting for Axis. Default false.

// if set, touching an axis will change the color of the nearest label
axis.setSnapHighlightToLabel(true);
axis.setHighlightColor(Color.RED);
Removing highlights

To remove single or multiple highlights, touch in a 'blank' area of the data (as defined by setMaxHighlightDistance above), touch the same entry twice, or the same axis at the same position twice. The latter action may be difficult to perform.

Multiple Highlights

For each highlightable item (each data set and each axis), either single or multiple highlights can be enabled:

item.setMultipleHighlightsEnabled(true);

If false, highlighting one item removes any existing highlight on that item. If true, multiple highlights can coexist.

Selection callbacks

This library two listeners for callbacks upon highlighting: OnChartValueSelectedListener and OnAxisSelectedListener. If both listeners exist, the onNothingSelected callback is made to the OnChartValueSelectedListener and not to the OnAxisSelectedListener.

OnChartValueSelectedListener

For callbacks when a data value has been selected for highlighting

public interface OnChartValueSelectedListener {
    /**
    * Called when a value has been selected inside the chart.
    *
    * @param e The selected Entry.
    * @param h The corresponding highlight object that contains information
    * about the highlighted position
    */
    public void onValueSelected(@Nullable Entry e, Highlight h);
    /**
    * Called when nothing has been selected or an "un-select" has been made.
    */
    public void onNothingSelected();
}

Simply let your class that should receive the callbacks implement this interface and set it as a listener to the chart:

chart.setOnChartValueSelectedListener(this);

OnAxisSelectedListener

For callbacks when an axis has been selected.

    /**
     * Called when an axis has been selected outside the chart.
     *
     * @param h highlight object that contains information
     *          about the highlighted position.
     */
    onAxisSelected(Highlight h);

    /**
    * Called when nothing has been selected or an "un-select" has been made.
    */
    public void onNothingSelected();

Simply let your class that should receive the callbacks implement this interface and set it as a listener to the chart::

chart.setOnAxisSelectedListener(this);

Highlighting programmatically

Highlight types

A highlight has a type: VALUE, X_AXIS, LEFT_AXIS, RIGHT _AXIS or NULL.

Each highlight can be queried for its type:

  • boolean isValue()
  • boolean isXAxis()
  • boolean isLeftAxis()
  • boolean isRightAxis()
  • boolean isNull()
  • Type getType()

There are a number of constructors available, including:

// for an axis highlight, create a highlight at the given x or y point.
// for a value highlight, search for the entry closest to x, y and highlight it.
Highlight(float xVal, float yVal, Type highlightType, float xPix, float yPix)

// if we already know which entry to highlight, set dataSetIndex 
// and dataIndex to skip the search
Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int dataIndex, YAxis.AxisDependency axis)

The Highlights class

The Highlights class holds a collection of Highlight s of a particular type. There can only be one 'Highlight Type' in an instance of Highlights, determined by the first Highlight added to the collection. Attempting to add a different type to a non-empty Highlights instance will throw a run time exception.

Methods
Getters

Each Highlight Type is gotten through different methods:

    VALUE: chart.getHighlights();
    
    X_AXIS: if (chart.hasXAxis)
                 chart.getXAxis().getHighlights();
                 
    LEFT_AXIS: if (chart.hasLeftAxis)
                 chart.getLeftAxis().getHighlights();
                 
    RIGHTT_AXIS: if (chart.hasRightAxis)
                 chart.getRightAxis().getHighlights();

You can skip the hasAxis checks if you are sure that the given axis exists, but you will get a run time exception if you are wrong.

Multiple highlights

Multiple highlights are supported at the Highlights level. Setting or getting these fields for a highlightable item simply passes the call through to the underlying `Highlights' class.

    setMultipleHighlightsEnabled(true);
    boolean isMultipleHighlightsEnabled();
Add / remove
    /**
     * Adds the given Highlight.
     * Deletes any pre-existing highlights if 
     * `isMultipleHighlightsEnabled` is false.
    */
    boolean add(Highlight highlight);
    
    /**
     * Removes the given highlight if it exists.
     *
     * @param highlight to be removed
     * @return true if highlight existed and was removed
     */
    public boolean remove(Highlight highlight)

    // clear all highlights
    void clear();  
Size
    int size();
    boolean isEmpty();
    boolean hasHighlights();  // same as isEmpty()
Iterating
    Iterator<Highlight> = highlights.iterator()

The Highlight class

The Highlight class represents all data associated with a highlight.

Fields
  • mType - Highlight.Type: VALUE, X_AXIS, LEFT_AXIS, RIGHT _AXIS or NULL

  • mX, mY - the x and y location in the data space

  • mXPx, mYPx - the x and y position on the screen in pixels

  • mDrawX, mDrawY - the position where the highlight was last drawn in pixels. The drawn position may be different than the pixel position. For example, a highlight on a bar chart is drawn above the bar. These values are set by the renderer, and may be null before any rendering has occurred.

  • mDataSetIndex - for VALUE, the index of the data set. Ignored otherwise.

  • mDataIndex - for VALUE, the index within the data set. Ignored otherwise

  • mStackIndex - for VALUE in the stacked BarEntry chart. Ignored otherwise

The indices are ignored for a non-VALUE Highlight and are generally set to -1.

VALUE highlight

The Highlight class provides several constructors for a VALUE Highlight:


 /** 
  *  Constructor for standard highlight.
  *  The data set will be searched for the entry closest to x.
 */
 public Highlight(float x, int dataSetIndex) { ... }

/**
 * Constructor where we know which entry to highlight.
 * This avoids the search overhead.
*/
public Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int dataIndex, YAxis.AxisDependency axis)
    
 /** constructor for stacked BarEntry highlight */
 public Highlight(float x, int dataSetIndex, int stackIndex) { ... }

The generic constructors below can also be used to create a Highlight by providing a VALUE type to those constructors.

Generic highlight

The Highlight class provides several constructors for a generic Highlight:

// Creates an 'empty' highlight of the given type.
// Generally used to return a NULL highlight rather
// than a null object - ala Kotlin.
Highlight(Type highlightType);

// constructor to support axis highlights with touch position
Highlight(float xVal, float yVal, Type highlightType, float xPix, float yPix)

Adding Highlights

To highlight a highlight item, simply create a Highlight with the appropriate type and add it to the chart. You need to provide both the xy data values and corresponding pixel position for constructors requiring either.

highlight the third[2] entry in the second[1] DataSet
Highlight highlight = new Highlight(xVal, yVal, xPx, yPx,
							dataSetIndex = 1, dataIndex = 2, 
							stackIndex = -1, YAxis.AxisDependency axis)
chart.addHighlight(highlight, true)
highlight the 12.2 point on the X axis
Highlight highlight = new Highlight(12.2f, yVal, highlightType = X_AXIS,
							xPix, yPix)
chart.addHighlight(highlight, true)
add multiple highlghts

To add multiple highlights, simply add highlights one at a time, or create a new Highlights and add it to the chart:

Highlights highlights = new Highlights();
highlights.setMultipleHighlightsEnabled(true);  // else they will be disabled
highlights.add(new Highlight(...));
... repeat as needed
chart.addHighlights(highlights);

Note that after addHighlights is called, mMultipleHighlightsEnabled is true only if it is true before the methd is called and if it is true in the added highlights.

Custom highlighter

All user input in the form of highlight gestures is internally processed by the default ChartHighlighter class. It is possible to replace the default highligher with a custom implementation using the below method:

  • setHighlighter(ChartHighlighter highlighter): Sets a custom highligher object for the chart that handles / processes all highlight touch events performed on the chart-view. Your custom highlighter object needs to extend the ChartHighlighter class.

regas99 avatar Mar 28 '19 01:03 regas99

Please @PhilJay , can you review and merge @regas99's PR

Zikstar avatar Feb 12 '20 13:02 Zikstar

Please merge this

eggham0518 avatar Feb 13 '20 02:02 eggham0518

merge plz..

hgcho0707 avatar Mar 23 '23 07:03 hgcho0707