I’m trying to find a way to apply a colour gradient to an existing FastLineRenderableSeries in the app. We want the colours in the gradient to align to specific y-axis values (see attached image)
- Marcela Guerra asked 1 month ago
- You must login to post comments
Yes, this can be done via the PaletteProvider feature: https://www.scichart.com/documentation/android/current/articles/chart2d/PaletteProvider%20API.html
Essentially:
- You implement a class that implements
IFillPaletteProviderIStrokePaletteProviderorIPointMarkerPaletteProviderdepending on your series type. For line series this would beIStrokePaletteProvider - You override the
update()getStrokeColors()getFillColors()getPointMarkerColorsmethods (getStrokeColors is sufficient for line series) - By returning a gradient color set for
getStrokeColors()based on Y-value you can achieve what you want.
In scichart.js we have a nice class called PaletteFactory that has a function called createYGradient that wraps this all up for you. Using the AI Assistant I’ve attempted porting this to Android. Please critique and if the implementation has issues, let me know and we can adjust
public class YGradientLinePaletteProvider
implements IStrokePaletteProvider /* and others if needed */ {
private final int[] colorMap;
private final double yMin;
private final double yMax;
public YGradientLinePaletteProvider(List<GradientStop> stops,
double yMin,
double yMax) {
this.colorMap = PaletteUtils.createColorMap(stops);
this.yMin = yMin;
this.yMax = yMax;
}
@Override
public void onAttached(@NonNull IRenderableSeries renderableSeries) {
// If you need the series, store it here
}
@Override
public void onDetached() {
// Cleanup if needed
}
@Override
public int overrideStrokeArgb(int index, double xValue, double yValue) {
// Map yValue to [0,1]
double range = yMax - yMin;
if (range <= 0) {
return colorMap[0];
}
double t = (yValue - yMin) / range;
if (t < 0) t = 0;
if (t > 1) t = 1;
int mapIndex = (int) Math.round(t * (colorMap.length - 1));
return colorMap[mapIndex];
}
}
PaletteUtils.createColorMap and GradientStop are defined as follows:
public class GradientStop {
public final float offset; // 0..1
public final int color; // ARGB
public GradientStop(float offset, int color) {
this.offset = offset;
this.color = color;
}
}
public final class PaletteUtils {
public static final int PRECISION = 500;
public static int[] createColorMap(List<GradientStop> stops) {
int[] colorMap = new int[PRECISION];
if (stops == null || stops.isEmpty()) {
// Fallback to white
Arrays.fill(colorMap, 0xFFFFFFFF);
return colorMap;
}
// Assume stops sorted by offset
float first = stops.get(0).offset;
float last = stops.get(stops.size() - 1).offset;
float diff = last - first;
float step = diff / (PRECISION - 1);
int count = stops.size();
int stopIndex = 0;
int prevColor = stops.get(0).color;
float prevOffset = stops.get(0).offset;
int nextColor = (count > 1) ? stops.get(1).color : prevColor;
float nextOffset = (count > 1) ? stops.get(1).offset : prevOffset;
float localDiff = nextOffset - prevOffset;
for (int i = 0; i < PRECISION; i++) {
float offset = first + i * step;
// Move to next segment if needed
while (offset >= nextOffset && stopIndex + 1 < count - 1) {
stopIndex++;
prevOffset = stops.get(stopIndex).offset;
prevColor = stops.get(stopIndex).color;
nextOffset = stops.get(stopIndex + 1).offset;
nextColor = stops.get(stopIndex + 1).color;
localDiff = nextOffset - prevOffset;
}
int color;
if (prevColor == nextColor || localDiff <= 1e-10f) {
color = nextColor;
} else {
float t = (offset - prevOffset) / localDiff;
color = lerpColor(prevColor, nextColor, t);
}
colorMap[i] = color;
}
return colorMap;
}
private static int lerpColor(int c0, int c1, float t) {
int a0 = (c0 >> 24) & 0xFF;
int r0 = (c0 >> 16) & 0xFF;
int g0 = (c0 >> 8) & 0xFF;
int b0 = c0 & 0xFF;
int a1 = (c1 >> 24) & 0xFF;
int r1 = (c1 >> 16) & 0xFF;
int g1 = (c1 >> 8) & 0xFF;
int b1 = c1 & 0xFF;
int a = (int) (a0 + (a1 - a0) * t);
int r = (int) (r0 + (r1 - r0) * t);
int g = (int) (g0 + (g1 - g0) * t);
int b = (int) (b0 + (b1 - b0) * t);
return (a << 24) | (r << 16) | (g << 8) | b;
}
}
Then, apply it to a line series
// Example gradient: blue -> green -> red
List<GradientStop> stops = Arrays.asList(
new GradientStop(0.0f, 0xFF3333FF),
new GradientStop(0.5f, 0xFF33FFAA),
new GradientStop(1.0f, 0xFFFF6600)
);
// Y range for gradient
double yMin = 0.0;
double yMax = 1.5;
YGradientLinePaletteProvider paletteProvider =
new YGradientLinePaletteProvider(stops, yMin, yMax);
FastLineRenderableSeries lineSeries = new FastLineRenderableSeries();
lineSeries.setDataSeries(dataSeries);
lineSeries.setStrokeThickness(3);
lineSeries.setPaletteProvider(paletteProvider);
surface.getRenderableSeries().add(lineSeries);
- Andrew Burnett-Thompson answered 4 weeks ago
- You must login to post comments
Please login first to submit.

