SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, iOS Chart, Android Chart and JavaScript Chart Components
SciChart Android ships with ~90Â Android Chart Examples which you can browse, play with, view the source-code and even export each SciChart Android Chart Example to a stand-alone Android Studio project. All of this is possible with the new and improved SciChart Android Examples Suite, which ships as part of our Android Charts SDK.
Demonstrates the Hit Test API, which can be used to get feedback about taps on data-points or lines and enable selection, or showing of context menus.
Example Usage
Tap anywhere on the chart to call BaseRenderableSeries.hitTest(). The method accepts coordinates of a touch point and returns the nearest data-point, plus its location in X,Y coordinate space.
The full source code for the Android Chart Hit-Test API example is included below (Scroll down!).
Did you know you can also view the source code from one of the following sources as well?
//******************************************************************************
// SCICHART® Copyright SciChart Ltd. 2011-2021. All rights reserved.
//
// Web: http://www.scichart.com
// Support: support@scichart.com
// Sales: sales@scichart.com
//
// HitTestDataPointsFragment.kt is part of SCICHART®, High Performance Scientific Charts
// For full terms and conditions of the license, see http://www.scichart.com/scichart-eula/
//
// This source code is protected by international copyright law. Unauthorized
// reproduction, reverse-engineering, or distribution of all or any portion of
// this source code is strictly prohibited.
//
// This source code contains confidential and proprietary trade secrets of
// SciChart Ltd., and should at no time be copied, transferred, sold,
// distributed or made available without express written permission.
//******************************************************************************
package com.scichart.examples.fragments.examples2d.tooltipsAndHitTest.kt
import android.annotation.SuppressLint
import android.graphics.PointF
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.animation.DecelerateInterpolator
import android.widget.Toast
import com.scichart.charting.visuals.SciChartSurface
import com.scichart.charting.visuals.axes.AxisAlignment.Bottom
import com.scichart.charting.visuals.axes.AxisAlignment.Left
import com.scichart.charting.visuals.renderableSeries.hitTest.HitTestInfo
import com.scichart.data.model.DoubleRange
import com.scichart.drawing.utility.ColorUtil
import com.scichart.examples.fragments.base.ExampleSingleChartBaseFragment
import com.scichart.examples.utils.scichartExtensions.*
@SuppressLint("ClickableViewAccessibility")
class HitTestDataPointsFragment: ExampleSingleChartBaseFragment(), View.OnTouchListener {
private var toast: Toast? = null
private val touchPoint = PointF()
private val hitTestInfo = HitTestInfo()
override fun initExample(surface: SciChartSurface) {
val xValues = listOf(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0)
val yValues = listOf(0.0, 0.1, 0.3, 0.5, 0.4, 0.35, 0.3, 0.25, 0.2, 0.1, 0.05)
surface.suspendUpdates {
xAxes { numericAxis { axisAlignment = Bottom } }
yAxes { numericAxis { axisAlignment = Left; growBy = DoubleRange(0.0, 0.1) } }
renderableSeries {
fastLineRenderableSeries {
xyDataSeries<Double, Double>("Line Series") {
append(xValues, yValues)
}
strokeStyle = SolidPenStyle(ColorUtil.SteelBlue, 3f)
ellipsePointMarker {
setSize(30)
fillStyle = SolidBrushStyle(ColorUtil.SteelBlue)
strokeStyle = SolidPenStyle(ColorUtil.Lavender, 2f)
}
scaleAnimation { interpolator = DecelerateInterpolator() }
}
fastMountainRenderableSeries {
xyDataSeries<Double, Double>("Mountain Series") {
append(xValues, yValues.map { it * 0.7 })
}
areaStyle = SolidBrushStyle(ColorUtil.LightSteelBlue)
strokeStyle = SolidPenStyle(ColorUtil.SteelBlue, 2f)
scaleAnimation { interpolator = DecelerateInterpolator() }
}
fastColumnRenderableSeries {
xyDataSeries<Double, Double>("Column Series") {
append(xValues, yValues.map { it * 0.5 })
}
scaleAnimation { interpolator = DecelerateInterpolator() }
}
fastCandlestickRenderableSeries {
ohlcDataSeries<Double, Double>("Candlestick Series") {
append(
xValues,
yValues.map { it + 0.5 },
yValues.map { it + 1.0 },
yValues.map { it + 0.3 },
yValues.map { it + 0.7 }
)
}
scaleAnimation { interpolator = DecelerateInterpolator(); zeroLine = 0.3 }
}
}
}
surface.setOnTouchListener(this)
}
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
val surface = v as SciChartSurface
event?.run { touchPoint.set(x, y) }
surface.translatePoint(touchPoint, surface.renderableSeriesArea)
val stringBuilder = StringBuilder()
stringBuilder.append(String.format("Touch at: (%.1f, %.1f)", touchPoint.x, touchPoint.y))
for (renderableSeries in surface.renderableSeries) {
renderableSeries.hitTest(hitTestInfo, touchPoint.x, touchPoint.y, 30f)
stringBuilder.append(String.format("\n%s - %s", renderableSeries.javaClass.simpleName, java.lang.Boolean.toString(hitTestInfo.isHit)))
}
toast?.run { cancel() }
toast = Toast.makeText(activity, null, Toast.LENGTH_SHORT).apply {
setGravity(Gravity.TOP or Gravity.CENTER, 0, 0)
setText(stringBuilder.toString())
show()
}
return true
}
}
//******************************************************************************
// SCICHART® Copyright SciChart Ltd. 2011-2021. All rights reserved.
//
// Web: http://www.scichart.com
// Support: support@scichart.com
// Sales: sales@scichart.com
//
// HitTestDatapointsFragment.java is part of SCICHART®, High Performance Scientific Charts
// For full terms and conditions of the license, see http://www.scichart.com/scichart-eula/
//
// This source code is protected by international copyright law. Unauthorized
// reproduction, reverse-engineering, or distribution of all or any portion of
// this source code is strictly prohibited.
//
// This source code contains confidential and proprietary trade secrets of
// SciChart Ltd., and should at no time be copied, transferred, sold,
// distributed or made available without express written permission.
//******************************************************************************
package com.scichart.examples.fragments.examples2d.tooltipsAndHitTest;
import android.annotation.SuppressLint;
import android.graphics.PointF;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.scichart.charting.model.dataSeries.IOhlcDataSeries;
import com.scichart.charting.model.dataSeries.IXyDataSeries;
import com.scichart.charting.model.dataSeries.OhlcDataSeries;
import com.scichart.charting.visuals.SciChartSurface;
import com.scichart.charting.visuals.axes.AxisAlignment;
import com.scichart.charting.visuals.axes.IAxis;
import com.scichart.charting.visuals.pointmarkers.EllipsePointMarker;
import com.scichart.charting.visuals.renderableSeries.FastCandlestickRenderableSeries;
import com.scichart.charting.visuals.renderableSeries.FastColumnRenderableSeries;
import com.scichart.charting.visuals.renderableSeries.FastLineRenderableSeries;
import com.scichart.charting.visuals.renderableSeries.FastMountainRenderableSeries;
import com.scichart.charting.visuals.renderableSeries.IRenderableSeries;
import com.scichart.charting.visuals.renderableSeries.hitTest.HitTestInfo;
import com.scichart.core.framework.UpdateSuspender;
import com.scichart.core.utility.ListUtil;
import com.scichart.data.model.DoubleRange;
import com.scichart.drawing.utility.ColorUtil;
import com.scichart.examples.fragments.base.ExampleSingleChartBaseFragment;
import java.util.Collections;
@SuppressLint("ClickableViewAccessibility")
public class HitTestDataPointsFragment extends ExampleSingleChartBaseFragment implements View.OnTouchListener {
private Toast toast;
private final PointF touchPoint = new PointF();
private final HitTestInfo hitTestInfo = new HitTestInfo();
@Override
public boolean showDefaultModifiersInToolbar() {
return false;
}
@Override
protected void initExample(@NonNull SciChartSurface surface) {
final Double[] xValues = {0d, 1d, 2d, 3d, 4d, 5d, 6d, 7d, 8d, 9d};
final Double[] yValues = {0d, 0.1d, 0.3d, 0.5d, 0.4d, 0.35d, 0.3d, 0.25d, 0.2d, 0.1d, 0.05d};
IXyDataSeries<Double, Double> dataSeries0 = sciChartBuilder.newXyDataSeries(Double.class, Double.class).withSeriesName("Line Series").build();
IXyDataSeries<Double, Double> dataSeries1 = sciChartBuilder.newXyDataSeries(Double.class, Double.class).withSeriesName("Mountain Series").build();
IXyDataSeries<Double, Double> dataSeries2 = sciChartBuilder.newXyDataSeries(Double.class, Double.class).withSeriesName("Column Series").build();
IOhlcDataSeries<Double, Double> dataSeries3 = sciChartBuilder.newOhlcDataSeries(Double.class, Double.class).withSeriesName("Candlestick Series").build();
dataSeries0.append(xValues, yValues);
dataSeries1.append(dataSeries0.getXValues(), ListUtil.select(dataSeries0.getYValues(), arg -> arg * 0.7d));
dataSeries2.append(dataSeries0.getXValues(), ListUtil.select(dataSeries0.getYValues(), arg -> arg * 0.5d));
dataSeries3.append(
dataSeries0.getXValues(),
ListUtil.select(dataSeries0.getYValues(), arg -> arg + 0.5d),
ListUtil.select(dataSeries0.getYValues(), arg -> arg + 1d),
ListUtil.select(dataSeries0.getYValues(), arg -> arg + 0.3d),
ListUtil.select(dataSeries0.getYValues(), arg -> arg + 0.7d)
);
final IAxis xAxis = sciChartBuilder.newNumericAxis().withAxisAlignment(AxisAlignment.Bottom).build();
final IAxis yAxis = sciChartBuilder.newNumericAxis().withAxisAlignment(AxisAlignment.Left).withGrowBy(new DoubleRange(0d, 0.1d)).build();
final FastLineRenderableSeries lineSeries = sciChartBuilder.newLineSeries()
.withDataSeries(dataSeries0)
.withStrokeStyle(ColorUtil.SteelBlue, 3)
.withPointMarker(sciChartBuilder.newPointMarker(new EllipsePointMarker())
.withSize(30, 30)
.withFill(ColorUtil.SteelBlue)
.withStroke(ColorUtil.Lavender, 2)
.build())
.build();
final FastMountainRenderableSeries mountainSeries = sciChartBuilder.newMountainSeries()
.withStrokeStyle(ColorUtil.SteelBlue, 2f)
.withAreaFillColor(ColorUtil.LightSteelBlue)
.withDataSeries(dataSeries1)
.build();
final FastColumnRenderableSeries columnSeries = sciChartBuilder.newColumnSeries()
.withDataSeries(dataSeries2)
.build();
final FastCandlestickRenderableSeries candlestickSeries = sciChartBuilder.newCandlestickSeries()
.withDataSeries(dataSeries3)
.build();
UpdateSuspender.using(surface, () -> {
Collections.addAll(surface.getXAxes(), xAxis);
Collections.addAll(surface.getYAxes(), yAxis);
Collections.addAll(surface.getRenderableSeries(), lineSeries, mountainSeries, columnSeries, candlestickSeries);
sciChartBuilder.newAnimator(mountainSeries).withScaleTransformation().withInterpolator(new DecelerateInterpolator()).withDuration(3000).withStartDelay(350).start();
sciChartBuilder.newAnimator(candlestickSeries).withScaleTransformation(0.3d).withInterpolator(new DecelerateInterpolator()).withDuration(3000).withStartDelay(350).start();
sciChartBuilder.newAnimator(lineSeries).withScaleTransformation().withInterpolator(new DecelerateInterpolator()).withDuration(3000).withStartDelay(350).start();
sciChartBuilder.newAnimator(columnSeries).withScaleTransformation().withInterpolator(new DecelerateInterpolator()).withDuration(3000).withStartDelay(350).start();
});
surface.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
final SciChartSurface surface = (SciChartSurface) v;
touchPoint.set(event.getX(), event.getY());
surface.translatePoint(touchPoint, surface.getRenderableSeriesArea());
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(String.format("Touch at: (%.1f, %.1f)", touchPoint.x, touchPoint.y));
for (IRenderableSeries renderableSeries : surface.getRenderableSeries()) {
renderableSeries.hitTest(hitTestInfo, touchPoint.x, touchPoint.y, 30);
stringBuilder.append(String.format("\n%s - %s", renderableSeries.getClass().getSimpleName(), Boolean.toString(hitTestInfo.isHit)));
}
if(toast != null) toast.cancel();
toast = Toast.makeText(getActivity(), null, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 0);
toast.setText(stringBuilder.toString());
toast.show();
return true;
}
}