Work on highlighting, introduced highlight max distance

This commit is contained in:
Philipp Jahoda 2016-06-03 10:26:05 +02:00
parent 423b885745
commit ac3eafaba9
8 changed files with 157 additions and 137 deletions

View file

@ -228,6 +228,7 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
// initialize the utils
Utils.init(getContext());
mMaxHighlightDistance = Utils.convertDpToPixel(70f);
mDefaultFormatter = new DefaultValueFormatter(1);
@ -483,6 +484,26 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
*/
protected Highlight[] mIndicesToHighlight;
/**
* The maximum distance in screen pixels away from an entry causing it to highlight.
*/
protected float mMaxHighlightDistance = 0f;
@Override
public float getMaxHighlightDistance() {
return mMaxHighlightDistance;
}
/**
* Sets the maximum distance in screen dp a touch can be away from an entry to cause it to get highlighted.
* Default: 70dp
*
* @param distDp
*/
public void setMaxHighlightDistance(float distDp) {
mMaxHighlightDistance = Utils.convertDpToPixel(distDp);
}
/**
* Returns the array of currently highlighted values. This might a null or
* empty array if nothing is highlighted.
@ -610,7 +631,7 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
high = null;
} else {
if (this instanceof BarLineChartBase
&& ((BarLineChartBase)this).isHighlightFullBarEnabled())
&& ((BarLineChartBase) this).isHighlightFullBarEnabled())
high = new Highlight(high.getX(), Float.NaN, -1, -1, -1);
// set the indices to highlight
@ -681,9 +702,9 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
float xVal = highlight.getX();
int dataSetIndex = highlight.getDataSetIndex();
float deltaX = mXAxis != null
? mXAxis.mAxisRange
: 1f;
float deltaX = mXAxis != null
? mXAxis.mAxisRange
: 1f;
if (xVal <= deltaX && xVal <= deltaX * mAnimator.getPhaseX()) {
@ -1539,7 +1560,8 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
* @param quality e.g. 50, min = 0, max = 100
* @return returns true if saving was successful, false if not
*/
public boolean saveToGallery(String fileName, String subFolderPath, String fileDescription, Bitmap.CompressFormat format, int quality) {
public boolean saveToGallery(String fileName, String subFolderPath, String fileDescription, Bitmap.CompressFormat
format, int quality) {
// restrain quality
if (quality < 0 || quality > 100)
quality = 50;

View file

@ -1,14 +1,24 @@
package com.github.mikephil.charting.formatter;
import com.github.mikephil.charting.data.DataSet;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.interfaces.datasets.IDataSet;
/**
* Interface that can be used to return a customized color instead of setting
* colors via the setColor(...) method of the DataSet.
*
*
* @author Philipp Jahoda
*/
public interface ColorFormatter {
int getColor(Entry e, int index);
/**
* Returns the color to be used for the given Entry at the given index (in the entries array)
*
* @param index index in the entries array
* @param e the entry to color
* @param set the DataSet the entry belongs to
* @return
*/
int getColor(int index, Entry e, IDataSet set);
}

View file

@ -9,6 +9,9 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
import com.github.mikephil.charting.interfaces.datasets.IDataSet;
import com.github.mikephil.charting.utils.PointD;
import com.github.mikephil.charting.utils.SelectionDetail;
import com.github.mikephil.charting.utils.Utils;
import java.util.List;
/**
* Created by Philipp Jahoda on 22/07/15.
@ -47,42 +50,6 @@ public class BarHighlighter extends ChartHighlighter<BarDataProvider> {
-1);
}
@Override
protected SelectionDetail getSelectionDetail(float xVal, float x, float y) {
BarData barData = mChart.getBarData();
int closestDataSetIndex = 0;
float closestDistance = Float.MAX_VALUE;
Entry closestEntry = null;
for (int i = 0; i < barData.getDataSets().size(); i++) {
IBarDataSet dataSet = barData.getDataSetByIndex(i);
final Entry entry = dataSet.getEntryForXPos(xVal);
if (entry != null) {
final float distance = Math.abs(xVal - entry.getX());
if (distance < closestDistance) {
closestDataSetIndex = i;
closestDistance = distance;
closestEntry = entry;
}
}
}
if(closestEntry == null)
return null;
return new SelectionDetail(x, y, closestEntry.getX(),
closestEntry.getY(),
closestDataSetIndex,
barData.getDataSetByIndex(closestDataSetIndex));
}
/**
* This method creates the Highlight object that also indicates which yValue of a stacked BarEntry has been
* selected.
@ -190,4 +157,9 @@ public class BarHighlighter extends ChartHighlighter<BarDataProvider> {
return ranges;
}
@Override
protected float getDistance(float x, float y, float selX, float selY) {
return Math.abs(x - selX);
}
}

View file

@ -71,18 +71,54 @@ public class ChartHighlighter<T extends BarLineScatterCandleBubbleDataProvider>
List<SelectionDetail> valsAtIndex = getSelectionDetailsAtIndex(xVal);
float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT);
float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT);
float leftdist = getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT);
float rightdist = getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT);
YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT;
SelectionDetail detail = Utils.getClosestSelectionDetailByPixel(valsAtIndex, x, y, axis);
SelectionDetail detail = getClosestSelectionDetailByPixel(valsAtIndex, x, y, axis, mChart
.getMaxHighlightDistance());
return detail;
}
/**
* Returns a list of SelectionDetail object corresponding to the given xIndex.
* Returns the minimum distance from a touch value (in pixels) to the
* closest value (in pixels) that is displayed in the chart.
*
* @param valsAtIndex
* @param pos
* @param axis
* @return
*/
protected float getMinimumDistance(List<SelectionDetail> valsAtIndex,
float pos,
YAxis.AxisDependency axis) {
float distance = Float.MAX_VALUE;
for (int i = 0; i < valsAtIndex.size(); i++) {
SelectionDetail sel = valsAtIndex.get(i);
if (sel.dataSet.getAxisDependency() == axis) {
float cdistance = Math.abs(getSelectionPos(sel) - pos);
if (cdistance < distance) {
distance = cdistance;
}
}
}
return distance;
}
protected float getSelectionPos(SelectionDetail sel) {
return sel.yPx;
}
/**
* Returns a list of SelectionDetail object corresponding to the given xVal.
*
* @param xVal
* @return
@ -116,4 +152,43 @@ public class ChartHighlighter<T extends BarLineScatterCandleBubbleDataProvider>
return new SelectionDetail((float) pixels.x, (float) pixels.y, e.getX(), e.getY(), dataSetIndex, set);
}
/**
* Returns the SelectionDetail of the DataSet that contains the closest yValue on the
* yPx-axis.
*
* @param valsAtIndex all the values at a specific index
* @return
*/
public SelectionDetail getClosestSelectionDetailByPixel(
List<SelectionDetail> valsAtIndex,
float x, float y,
YAxis.AxisDependency axis, float minSelectionDistance) {
SelectionDetail closest = null;
float distance = minSelectionDistance;
System.out.println(distance);
for (int i = 0; i < valsAtIndex.size(); i++) {
SelectionDetail sel = valsAtIndex.get(i);
if (axis == null || sel.dataSet.getAxisDependency() == axis) {
float cDistance = getDistance(x, y, sel.xPx, sel.yPx);
if (cDistance < distance) {
closest = sel;
distance = cDistance;
}
}
}
return closest;
}
protected float getDistance(float x, float y, float selX, float selY) {
return (float) Math.hypot(x - selX, y - selY);
}
}

View file

@ -1,10 +1,17 @@
package com.github.mikephil.charting.highlight;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.DataSet;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
import com.github.mikephil.charting.interfaces.datasets.IDataSet;
import com.github.mikephil.charting.utils.PointD;
import com.github.mikephil.charting.utils.SelectionDetail;
import com.github.mikephil.charting.utils.Utils;
import java.util.List;
/**
* Created by Philipp Jahoda on 22/07/15.
@ -22,7 +29,7 @@ public class HorizontalBarHighlighter extends BarHighlighter {
PointD pos = getValsForTouch(y, x);
SelectionDetail selectionDetail = getSelectionDetail((float) pos.y, x, y);
SelectionDetail selectionDetail = getSelectionDetail((float) pos.y, y, x);
if (selectionDetail == null)
return null;
@ -42,4 +49,19 @@ public class HorizontalBarHighlighter extends BarHighlighter {
selectionDetail.dataSetIndex,
-1);
}
@Override
protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) {
final Entry e = set.getEntryForXPos(xVal, rounding);
PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getY(), e.getX());
return new SelectionDetail((float) pixels.x, (float) pixels.y, e.getX(), e.getY(), dataSetIndex, set);
}
@Override
protected float getDistance(float x, float y, float selX, float selY) {
return Math.abs(y - selY);
}
}

View file

@ -5,6 +5,7 @@ import android.graphics.RectF;
import com.github.mikephil.charting.data.ChartData;
import com.github.mikephil.charting.formatter.ValueFormatter;
import com.github.mikephil.charting.utils.Utils;
/**
* Interface that provides everything there is to know about the dimensions,
@ -44,6 +45,13 @@ public interface ChartInterface {
*/
float getYChartMax();
/**
* Returns the maximum distance in scren dp a touch can be away from an entry to cause it to get highlighted.
*
* @return
*/
float getMaxHighlightDistance();
int getWidth();
int getHeight();

View file

@ -300,31 +300,6 @@ public class ScatterChartRenderer extends LineScatterCandleRadarRenderer {
default:
break;
}
// else { // draw the custom-shape
//
// Path customShape = dataSet.getCustomScatterShape();
//
// for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j += 2) {
//
// Entry e = entries.get(j / 2);
//
// if (!fitsBounds(e.getX(), mMinX, mMaxX))
// continue;
//
// if (customShape == null)
// return;
//
// mRenderPaint.setColor(dataSet.getColor(j));
//
// Path newPath = new Path(customShape);
// newPath.offset(e.getX(), e.getY());
//
// // transform the provided custom path
// trans.pathValueToPixel(newPath);
// c.drawPath(newPath, mRenderPaint);
// }
// }
}
@Override

View file

@ -431,70 +431,6 @@ public abstract class Utils {
return closest;
}
/**
* Returns the SelectionDetail of the DataSet that contains the closest yValue on the
* yPx-axis.
*
* @param valsAtIndex all the values at a specific index
* @return
*/
public static SelectionDetail getClosestSelectionDetailByPixel(
List<SelectionDetail> valsAtIndex,
float x, float y,
AxisDependency axis) {
SelectionDetail closest = null;
float distance = Float.MAX_VALUE;
for (int i = 0; i < valsAtIndex.size(); i++) {
SelectionDetail sel = valsAtIndex.get(i);
if (axis == null || sel.dataSet.getAxisDependency() == axis) {
float cDistance = (float) Math.hypot(x - sel.xPx, y - sel.yPx);
if (cDistance < distance) {
closest = sel;
distance = cDistance;
}
}
}
return closest;
}
/**
* Returns the minimum distance from a touch-yPx-yValue (in pixels) to the
* closest yPx-yValue (in pixels) that is displayed in the chart.
*
* @param valsAtIndex
* @param y
* @param axis
* @return
*/
public static float getMinimumDistance(List<SelectionDetail> valsAtIndex,
float y,
AxisDependency axis) {
float distance = Float.MAX_VALUE;
for (int i = 0; i < valsAtIndex.size(); i++) {
SelectionDetail sel = valsAtIndex.get(i);
if (sel.dataSet.getAxisDependency() == axis) {
float cdistance = Math.abs(sel.yPx - y);
if (cdistance < distance) {
distance = cdistance;
}
}
}
return distance;
}
/**
* If this component has no ValueFormatter or is only equipped with the
* default one (no custom set), return true.