This commit is contained in:
coco
2026-07-03 15:56:07 +08:00
commit caef23209c
5767 changed files with 1004268 additions and 0 deletions
@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.androidplot.demos">
<!-- Used by Crittercism to report crashes -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application android:name=".DemoApplication"
android:label="Androidplot API DemoApp"
android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen"
android:icon="@drawable/ic_launcher">
<activity android:name=".MainActivity"
android:label="@string/app_name"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SimplePieChartActivity"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".AnimatedXYPlotActivity"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SimpleXYPlotActivity"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ScatterPlotActivity"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".BarPlotExampleActivity"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".DynamicXYPlotActivity"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".CandlestickChartActivity"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".OrientationSensorExampleActivity"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".StepChartExampleActivity"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".TouchZoomExampleActivity"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ListViewActivity" android:label="ListView Example"/>
<activity android:name=".RecyclerViewActivity" android:label="RecyclerView Example"/>
<activity android:name=".XYRegionExampleActivity" android:label="XYRegion Example"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".TimeSeriesActivity"/>
<activity android:name=".XYPlotWithBgImgActivity"/>
<activity android:name=".ECGExample"/>
<activity android:name=".FXPlotExampleActivity"/>
<activity android:name=".BubbleChartActivity"/>
<activity android:name=".DualScaleActivity"/>
<!-- receiver for demo app widget -->
<receiver
android:icon="@drawable/ic_launcher"
android:label="Example Widget"
android:name="com.androidplot.demos.widget.DemoAppWidgetProvider"
android:exported="false">
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/demo_app_widget_provider_info" />
</receiver>
</application>
</manifest>
@@ -0,0 +1,158 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import androidx.annotation.NonNull;
import android.view.animation.AccelerateDecelerateInterpolator;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.CatmullRomInterpolator;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.ScalingXYSeries;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Arrays;
/**
* Demonstrates animating XYSeries data from a zero value up/down to the actual values set. Once
* the animation completes, labels for each point are made visible.
*
* IMPORTANT: This example makes use of {@link ValueAnimator} which is only available in
* SDK level 11 and later..
*/
public class AnimatedXYPlotActivity extends Activity {
private XYPlot plot;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_xy_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
// create a couple arrays of y-values to plot:
final Number[] domainLabels = {1, 2, 3, 6, 7, 8, 9, 10, 13, 14};
Number[] series1Numbers = {1, 4, 2, 8, 4, 16, 8, 32, 16, 64};
Number[] series2Numbers = {5, 2, 10, 5, 20, 10, 40, 20, 80, 40};
// turn the above arrays into XYSeries':
// (Y_VALS_ONLY means use the element index as the x value)
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series1");
XYSeries series2 = new SimpleXYSeries(
Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
final LineAndPointFormatter series1Format =
new LineAndPointFormatter(this, R.xml.line_point_formatter);
final LineAndPointFormatter series2Format =
new LineAndPointFormatter(this, R.xml.line_point_formatter);
series2Format.getLinePaint().setColor(Color.RED);
// just for fun, add some smoothing to the lines:
// see: http://androidplot.com/smooth-curves-and-androidplot/
series1Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
series2Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
// wrap each series in instances of ScalingXYSeries before adding to the plot
// so that we can animate the series values below:
final ScalingXYSeries scalingSeries1 = new ScalingXYSeries(series1, 0, ScalingXYSeries.Mode.Y_ONLY);
plot.addSeries(scalingSeries1, series1Format);
final ScalingXYSeries scalingSeries2 = new ScalingXYSeries(series2, 0, ScalingXYSeries.Mode.Y_ONLY);
plot.addSeries(scalingSeries2, series2Format);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
@Override
public StringBuffer format(Object obj,
@NonNull StringBuffer toAppendTo,
@NonNull FieldPosition pos) {
int i = Math.round(((Number) obj).floatValue());
return toAppendTo.append(domainLabels[i]);
}
@Override
public Object parseObject(String source, @NonNull ParsePosition pos) {
return null;
}
});
plot.setRangeBoundaries(0, 100, BoundaryMode.FIXED);
// animate a scale value from a starting val of 0 to a final value of 1:
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
// use an animation pattern that begins and ends slowly:
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float scale = valueAnimator.getAnimatedFraction();
scalingSeries1.setScale(scale);
scalingSeries2.setScale(scale);
plot.redraw();
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
// the animation is over, so show point labels:
series1Format.getPointLabelFormatter().getTextPaint().setColor(Color.WHITE);
series2Format.getPointLabelFormatter().getTextPaint().setColor(Color.WHITE);
plot.redraw();
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
// the animation will run for 1.5 seconds:
animator.setDuration(1500);
animator.start();
}
}
@@ -0,0 +1,467 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import java.text.DateFormatSymbols;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.Arrays;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.SeekBar;
import android.widget.Spinner;
import com.androidplot.Region;
import com.androidplot.ui.*;
import com.androidplot.ui.widget.TextLabelWidget;
import com.androidplot.util.*;
import com.androidplot.xy.*;
/**
* An example of a Bar Plot.
*/
public class BarPlotExampleActivity extends Activity {
private static final String NO_SELECTION_TXT = "Touch bar to select.";
private XYPlot plot;
private CheckBox series1CheckBox;
private CheckBox series2CheckBox;
private Spinner spRenderStyle, spWidthStyle, spSeriesSize;
private SeekBar sbFixedWidth, sbVariableWidth;
private XYSeries series1;
private XYSeries series2;
private enum SeriesSize {
TEN,
TWENTY,
SIXTY
}
// Create a couple arrays of y-values to plot:
Number[] series1Numbers10 = {2, null, 5, 2, 7, 4, 3, 7, 4, 5};
Number[] series2Numbers10 = {4, 6, 3, null, 2, 0, 7, 4, 5, 4};
Number[] series1Numbers20 = {2, null, 5, 2, 7, 4, 3, 7, 4, 5, 7, 4, 5, 8, 5, 3, 6, 3, 9, 3};
Number[] series2Numbers20 = {4, 6, 3, null, 2, 0, 7, 4, 5, 4, 9, 6, 2, 8, 4, 0, 7, 4, 7, 9};
Number[] series1Numbers60 = {2, null, 5, 2, 7, 4, 3, 7, 4, 5, 7, 4, 5, 8, 5, 3, 6, 3, 9, 3, 2, null, 5, 2, 7, 4, 3, 7, 4, 5, 7, 4, 5, 8, 5, 3, 6, 3, 9, 3, 2, null, 5, 2, 7, 4, 3, 7, 4, 5, 7, 4, 5, 8, 5, 3, 6, 3, 9, 3};
Number[] series2Numbers60 = {4, 6, 3, null, 2, 0, 7, 4, 5, 4, 9, 6, 2, 8, 4, 0, 7, 4, 7, 9, 4, 6, 3, null, 2, 0, 7, 4, 5, 4, 9, 6, 2, 8, 4, 0, 7, 4, 7, 9, 4, 6, 3, null, 2, 0, 7, 4, 5, 4, 9, 6, 2, 8, 4, 0, 7, 4, 7, 9};
Number[] series1Numbers = series1Numbers10;
Number[] series2Numbers = series2Numbers10;
private MyBarFormatter formatter1;
private MyBarFormatter formatter2;
private MyBarFormatter selectionFormatter;
private TextLabelWidget selectionWidget;
private Pair<Integer, XYSeries> selection;
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bar_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
formatter1 = new MyBarFormatter(Color.rgb(100, 150, 100), Color.LTGRAY);
formatter1.setMarginLeft(PixelUtils.dpToPix(1));
formatter1.setMarginRight(PixelUtils.dpToPix(1));
formatter2 = new MyBarFormatter(Color.rgb(100, 100, 150), Color.LTGRAY);
formatter2.setMarginLeft(PixelUtils.dpToPix(1));
formatter2.setMarginRight(PixelUtils.dpToPix(1));
selectionFormatter = new MyBarFormatter(Color.YELLOW, Color.WHITE);
selectionWidget = new TextLabelWidget(plot.getLayoutManager(), NO_SELECTION_TXT,
new Size(
PixelUtils.dpToPix(100), SizeMode.ABSOLUTE,
PixelUtils.dpToPix(100), SizeMode.ABSOLUTE),
TextOrientation.HORIZONTAL);
selectionWidget.getLabelPaint().setTextSize(PixelUtils.dpToPix(16));
// add a dark, semi-transparent background to the selection label widget:
Paint p = new Paint();
p.setARGB(100, 0, 0, 0);
selectionWidget.setBackgroundPaint(p);
selectionWidget.position(
0, HorizontalPositioning.RELATIVE_TO_CENTER,
PixelUtils.dpToPix(45), VerticalPositioning.ABSOLUTE_FROM_TOP,
Anchor.TOP_MIDDLE);
selectionWidget.pack();
// reduce the number of range labels
plot.setLinesPerRangeLabel(3);
plot.setRangeLowerBoundary(0, BoundaryMode.FIXED);
plot.setLinesPerDomainLabel(2);
// setup checkbox listers:
series1CheckBox = (CheckBox) findViewById(R.id.s1CheckBox);
series1CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
onS1CheckBoxClicked(b);
}
});
series2CheckBox = (CheckBox) findViewById(R.id.s2CheckBox);
series2CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
onS2CheckBoxClicked(b);
}
});
plot.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
onPlotClicked(new PointF(motionEvent.getX(), motionEvent.getY()));
}
return true;
}
});
spRenderStyle = (Spinner) findViewById(R.id.spRenderStyle);
ArrayAdapter<BarRenderer.BarOrientation> adapter = new ArrayAdapter<BarRenderer.BarOrientation>(this,
android.R.layout.simple_spinner_item, BarRenderer.BarOrientation
.values());
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spRenderStyle.setAdapter(adapter);
spRenderStyle.setSelection(BarRenderer.BarOrientation.OVERLAID.ordinal());
spRenderStyle.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
updatePlot();
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
spWidthStyle = (Spinner) findViewById(R.id.spWidthStyle);
ArrayAdapter<BarRenderer.BarGroupWidthMode> adapter1 = new ArrayAdapter<BarRenderer.BarGroupWidthMode>(
this, android.R.layout.simple_spinner_item, BarRenderer.BarGroupWidthMode
.values());
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spWidthStyle.setAdapter(adapter1);
spWidthStyle.setSelection(BarRenderer.BarGroupWidthMode.FIXED_WIDTH.ordinal());
spWidthStyle.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
if (BarRenderer.BarGroupWidthMode.FIXED_WIDTH.equals(spWidthStyle.getSelectedItem())) {
sbFixedWidth.setVisibility(View.VISIBLE);
sbVariableWidth.setVisibility(View.INVISIBLE);
} else {
sbFixedWidth.setVisibility(View.INVISIBLE);
sbVariableWidth.setVisibility(View.VISIBLE);
}
updatePlot();
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
spSeriesSize = (Spinner) findViewById(R.id.spSeriesSize);
ArrayAdapter<SeriesSize> adapter11 = new ArrayAdapter<SeriesSize>(this,
android.R.layout.simple_spinner_item, SeriesSize.values());
adapter11.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spSeriesSize.setAdapter(adapter11);
spSeriesSize.setSelection(SeriesSize.TEN.ordinal());
spSeriesSize.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
final SeriesSize selectedSize = (SeriesSize) arg0.getSelectedItem();
switch (selectedSize) {
case TEN:
series1Numbers = series1Numbers10;
series2Numbers = series2Numbers10;
break;
case TWENTY:
series1Numbers = series1Numbers20;
series2Numbers = series2Numbers20;
break;
case SIXTY:
series1Numbers = series1Numbers60;
series2Numbers = series2Numbers60;
break;
default:
break;
}
updatePlot(selectedSize);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
sbFixedWidth = (SeekBar) findViewById(R.id.sbFixed);
sbFixedWidth.setProgress(50);
sbFixedWidth.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
updatePlot();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
sbVariableWidth = (SeekBar) findViewById(R.id.sbVariable);
sbVariableWidth.setProgress(1);
sbVariableWidth.setVisibility(View.INVISIBLE);
sbVariableWidth.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
updatePlot();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).
setFormat(new NumberFormat() {
@Override
public StringBuffer format(double value, StringBuffer buffer,
FieldPosition field) {
int year = (int) (value + 0.5d) / 12;
int month = (int) ((value + 0.5d) % 12);
return new StringBuffer(DateFormatSymbols.getInstance()
.getShortMonths()[month] + " '0" + year);
}
@Override
public StringBuffer format(long value, StringBuffer buffer,
FieldPosition field) {
throw new UnsupportedOperationException("Not yet implemented.");
}
@Override
public Number parse(String string, ParsePosition position) {
throw new UnsupportedOperationException("Not yet implemented.");
}
});
updatePlot();
}
private void updatePlot() {
updatePlot(null);
}
private void updatePlot(SeriesSize seriesSize) {
// Remove all current series from each plot
plot.clear();
// Setup our Series with the selected number of elements
series1 = new SimpleXYSeries(Arrays.asList(series1Numbers),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Us");
series2 = new SimpleXYSeries(Arrays.asList(series2Numbers),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Them");
plot.setDomainBoundaries(-1, series1.size(), BoundaryMode.FIXED);
plot.setRangeUpperBoundary(
SeriesUtils.minMax(series1, series2).
getMaxY().doubleValue() + 1, BoundaryMode.FIXED);
if(seriesSize != null) {
switch(seriesSize) {
case TEN:
plot.setDomainStep(StepMode.INCREMENT_BY_VAL, 2);
break;
case TWENTY:
plot.setDomainStep(StepMode.INCREMENT_BY_VAL, 4);
break;
case SIXTY:
plot.setDomainStep(StepMode.INCREMENT_BY_VAL, 6);
break;
}
}
// add a new series' to the xyplot:
if (series1CheckBox.isChecked()) plot.addSeries(series1, formatter1);
if (series2CheckBox.isChecked()) plot.addSeries(series2, formatter2);
// Setup the BarRenderer with our selected options
MyBarRenderer renderer = plot.getRenderer(MyBarRenderer.class);
renderer.setBarOrientation((BarRenderer.BarOrientation) spRenderStyle.getSelectedItem());
final BarRenderer.BarGroupWidthMode barGroupWidthMode
= (BarRenderer.BarGroupWidthMode) spWidthStyle.getSelectedItem();
renderer.setBarGroupWidth(barGroupWidthMode,
barGroupWidthMode == BarRenderer.BarGroupWidthMode.FIXED_WIDTH
? sbFixedWidth.getProgress() : sbVariableWidth.getProgress());
if (BarRenderer.BarOrientation.STACKED.equals(spRenderStyle.getSelectedItem())) {
plot.getInnerLimits().setMaxY(15);
} else {
plot.getInnerLimits().setMaxY(0);
}
plot.redraw();
}
private void onPlotClicked(PointF point) {
// make sure the point lies within the graph area. we use gridrect
// because it accounts for margins and padding as well.
if (plot.containsPoint(point.x, point.y)) {
Number x = plot.getXVal(point);
Number y = plot.getYVal(point);
selection = null;
double xDistance = 0;
double yDistance = 0;
// find the closest value to the selection:
for (SeriesBundle<XYSeries, ? extends XYSeriesFormatter> sfPair : plot
.getRegistry().getSeriesAndFormatterList()) {
XYSeries series = sfPair.getSeries();
for (int i = 0; i < series.size(); i++) {
Number thisX = series.getX(i);
Number thisY = series.getY(i);
if (thisX != null && thisY != null) {
double thisXDistance =
Region.measure(x, thisX).doubleValue();
double thisYDistance =
Region.measure(y, thisY).doubleValue();
if (selection == null) {
selection = new Pair<>(i, series);
xDistance = thisXDistance;
yDistance = thisYDistance;
} else if (thisXDistance < xDistance) {
selection = new Pair<>(i, series);
xDistance = thisXDistance;
yDistance = thisYDistance;
} else if (thisXDistance == xDistance &&
thisYDistance < yDistance &&
thisY.doubleValue() >= y.doubleValue()) {
selection = new Pair<>(i, series);
xDistance = thisXDistance;
yDistance = thisYDistance;
}
}
}
}
} else {
// if the press was outside the graph area, deselect:
selection = null;
}
if (selection == null) {
selectionWidget.setText(NO_SELECTION_TXT);
} else {
selectionWidget.setText("Selected: " + selection.second.getTitle() +
" Value: " + selection.second.getY(selection.first));
}
plot.redraw();
}
private void onS1CheckBoxClicked(boolean checked) {
if (checked) {
plot.addSeries(series1, formatter1);
} else {
plot.removeSeries(series1);
}
plot.redraw();
}
private void onS2CheckBoxClicked(boolean checked) {
if (checked) {
plot.addSeries(series2, formatter2);
} else {
plot.removeSeries(series2);
}
plot.redraw();
}
class MyBarFormatter extends BarFormatter {
public MyBarFormatter(int fillColor, int borderColor) {
super(fillColor, borderColor);
}
@Override
public Class<? extends SeriesRenderer> getRendererClass() {
return MyBarRenderer.class;
}
@Override
public SeriesRenderer doGetRendererInstance(XYPlot plot) {
return new MyBarRenderer(plot);
}
}
class MyBarRenderer extends BarRenderer<MyBarFormatter> {
public MyBarRenderer(XYPlot plot) {
super(plot);
}
/**
* Implementing this method to allow us to inject our
* special selection getFormatter.
* @param index index of the point being rendered.
* @param series XYSeries to which the point being rendered belongs.
* @return
*/
@Override
public MyBarFormatter getFormatter(int index, XYSeries series) {
if (selection != null &&
selection.second == series &&
selection.first == index) {
return selectionFormatter;
} else {
return getFormatter(series);
}
}
}
}
@@ -0,0 +1,71 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.*;
import android.graphics.*;
import android.os.*;
import com.androidplot.xy.*;
import java.util.*;
/**
* An example of a bubble chart.
*/
public class BubbleChartActivity extends Activity {
private XYPlot plot;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.bubble_chart_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
// turn the above arrays into XYSeries':
// (Y_VALS_ONLY means use the element index as the x value)
BubbleSeries series1 = new BubbleSeries(
Arrays.asList(new Number[]{3, 5, 2, 3, 6}),
Arrays.asList(new Number[]{1, 5, 2, 2, 3}), "s1");
BubbleSeries series2 = new BubbleSeries(
Arrays.asList(new Number[]{2, 7, 3, 1, 3}),
Arrays.asList(new Number[]{2, 1, 2, 6, 7}), "s2");
BubbleSeries series3 = new BubbleSeries(
Arrays.asList(new Number[]{7, 2, 5, 6, 5}),
Arrays.asList(new Number[]{3, 2, 4, 6, 7}), "s3");
plot.setDomainBoundaries(-1, 5, BoundaryMode.FIXED);
plot.setRangeBoundaries(0, 8, BoundaryMode.FIXED);
BubbleFormatter bf1 = new BubbleFormatter(this, R.xml.bubble_formatter1);
bf1.setPointLabelFormatter(new PointLabelFormatter(Color.BLACK));
bf1.getPointLabelFormatter().getTextPaint().setTextAlign(Paint.Align.CENTER);
bf1.getPointLabelFormatter().getTextPaint().setFakeBoldText(true);
// add series to the xyplot:
plot.addSeries(series1, bf1);
plot.addSeries(series2, new BubbleFormatter(this, R.xml.bubble_formatter2));
plot.addSeries(series3, new BubbleFormatter(this, R.xml.bubble_formatter3));
PanZoom.attach(plot);
}
}
@@ -0,0 +1,167 @@
/*
* Copyright 2016 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.androidplot.Region;
import com.androidplot.util.PixelUtils;
import com.androidplot.util.SeriesUtils;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.CandlestickFormatter;
import com.androidplot.xy.CandlestickMaker;
import com.androidplot.xy.CandlestickSeries;
import com.androidplot.xy.CatmullRomInterpolator;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.PointLabelFormatter;
import com.androidplot.xy.PointLabeler;
import com.androidplot.xy.StepMode;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
/**
* A simple example of a candlestick chart rendered on an {@link XYPlot}.
*/
public class CandlestickChartActivity extends Activity {
private XYPlot plot;
private DecimalFormat currencyFormat = new DecimalFormat("$0.00");
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.candlestick_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
final CandlestickSeries candlestickSeries = new CandlestickSeries(
new CandlestickSeries.Item(1, 10, 2, 9.04),
new CandlestickSeries.Item(4, 18, 6, 5.50),
new CandlestickSeries.Item(3, 11, 5, 9.21),
new CandlestickSeries.Item(2, 17, 2, 15.25),
new CandlestickSeries.Item(6, 11, 11, 7.12),
new CandlestickSeries.Item(8, 16, 10, 15.02));
// draw a simple line plot of the close vals:
LineAndPointFormatter lpf = new LineAndPointFormatter(Color.BLACK, Color.BLACK, null, null);
lpf.getLinePaint().setPathEffect(
new DashPathEffect(
new float[] {PixelUtils.dpToPix(5), PixelUtils.dpToPix(5)}, 0));
lpf.setInterpolationParams(
new CatmullRomInterpolator.Params(20, CatmullRomInterpolator.Type.Centripetal));
plot.addSeries(candlestickSeries.getCloseSeries(), lpf);
CandlestickFormatter formatter = new CandlestickFormatter(this, R.xml.candlestick_formatter);
// draw candlestick bodies as triangles instead of squares:
// triangles will point up for items that closed higher than they opened
// and down for those that closed lower:
formatter.setBodyStyle(CandlestickFormatter.BodyStyle.SQUARE);
// add the candlestick series data to the plot:
CandlestickMaker.make(plot, formatter, candlestickSeries);
// setup the range tick label formatting, etc:
plot.setLinesPerRangeLabel(3);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).
setFormat(currencyFormat);
// add some padding to range boundaries:
final Region minMax = SeriesUtils.minMax(
candlestickSeries.getHighSeries().getyVals(),
candlestickSeries.getLowSeries().getyVals());
plot.setRangeBoundaries(
minMax.getMin().doubleValue() - 1,
minMax.getMax().doubleValue() + 1,
BoundaryMode.FIXED);
// setup the domain tick label formatting, etc:
plot.setDomainBoundaries(-1, 6, BoundaryMode.FIXED);
plot.setDomainStep(StepMode.INCREMENT_BY_VAL, 1);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
@Override
public StringBuffer format(Object object, @NonNull StringBuffer buffer,
@NonNull FieldPosition field) {
int day = ((Number) object).intValue() % 7;
switch (day) {
case 0:
buffer.append("Sun");
break;
case 1:
buffer.append("Mon");
break;
case 2:
buffer.append("Tues");
break;
case 3:
buffer.append("Wed");
break;
case 4:
buffer.append("Thurs");
break;
case 5:
buffer.append("Fri");
break;
case 6:
buffer.append("Sat");
default:
// show nothing
}
return buffer;
}
@Override
public Object parseObject(String string, @NonNull ParsePosition position) {
return null;
}
});
formatter.setPointLabelFormatter(
new PointLabelFormatter(Color.BLACK, PixelUtils.dpToPix(8), 0));
formatter.getPointLabelFormatter().getTextPaint().setFakeBoldText(true);
formatter.getPointLabelFormatter().getTextPaint().setTextAlign(Paint.Align.LEFT);
// add labels for close vals:
formatter.setPointLabeler(new PointLabeler() {
@Override
public String getLabel(XYSeries series, int index) {
if(series == candlestickSeries.getCloseSeries()) {
return currencyFormat.format(series.getY(index).doubleValue());
}
return null;
}
});
}
}
@@ -0,0 +1,11 @@
package com.androidplot.demos;
import android.app.*;
public class DemoApplication extends Application {
@Override public void onCreate() {
super.onCreate();
}
}
@@ -0,0 +1,158 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.CatmullRomInterpolator;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.NormedXYSeries;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.StepMode;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Arrays;
/**
* Demonstrates normalizing series data using {@link com.androidplot.xy.NormedXYSeries}
* and displaying a dual scale on an XYPlot.
*
* This particular example displays the yearly cost of raising of a child along the federal
* minimum wage from 2012 to 2016.
*
*/
public class DualScaleActivity extends Activity {
private XYPlot plot;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.dual_scale_example);
plot = (XYPlot) findViewById(R.id.plot);
Number[] childCosts = {5500, 5550,5496, 5800, 5815};
Number[] minWages = {9, 9, 9, 9, 10};
// create and normalize series data:
final NormedXYSeries costsSeries = new NormedXYSeries(new SimpleXYSeries(
Arrays.asList(childCosts), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Yearly Cost"));
final NormedXYSeries minWageSeries = new NormedXYSeries(new SimpleXYSeries(
Arrays.asList(minWages), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Min Wage"));
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
LineAndPointFormatter childCostsFormat =
new LineAndPointFormatter(this, R.xml.line_point_formatter_with_labels);
childCostsFormat.setVertexPaint(null);
childCostsFormat.setPointLabelFormatter(null);
LineAndPointFormatter minWageFormat =
new LineAndPointFormatter(this, R.xml.line_point_formatter_with_labels_2);
minWageFormat.setVertexPaint(null);
minWageFormat.setPointLabelFormatter(null);
// add an "dash" effect to the series2 line:
minWageFormat.getLinePaint().setPathEffect(new DashPathEffect(new float[] {
// always use DP when specifying pixel sizes, to keep things consistent across devices:
PixelUtils.dpToPix(20),
PixelUtils.dpToPix(15)}, 0));
// add some smoothing to the lines:
// see: http://androidplot.com/smooth-curves-and-androidplot/
childCostsFormat.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
minWageFormat.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
// add a new series' to the xyplot:
plot.addSeries(costsSeries, childCostsFormat);
plot.addSeries(minWageSeries, minWageFormat);
plot.setRangeBoundaries(-1, 2, BoundaryMode.FIXED);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).getPaint().setColor(Color.GREEN);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).setFormat(new Format() {
final DecimalFormat df = new DecimalFormat("$#,###");
@Override
public StringBuffer format(Object o, @NonNull StringBuffer stringBuffer,
@NonNull FieldPosition fieldPosition) {
final Number cost = costsSeries.denormalizeYVal((Number) o);
stringBuffer.append(df.format(cost.doubleValue()));
return stringBuffer;
}
@Override
public Object parseObject(String s, @NonNull ParsePosition parsePosition) {
return null;
}
});
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.RIGHT).getPaint().setColor(Color.BLUE);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.RIGHT).setFormat(new Format() {
final DecimalFormat df = new DecimalFormat("$#.##");
@Override
public StringBuffer format(Object o, @NonNull StringBuffer stringBuffer,
@NonNull FieldPosition fieldPosition) {
Number minWage = minWageSeries.denormalizeYVal((Number) o);
stringBuffer.append(df.format(minWage.doubleValue()));
return stringBuffer;
}
@Override
public Object parseObject(String s, @NonNull ParsePosition parsePosition) {
return null;
}
});
plot.setDomainStep(StepMode.INCREMENT_BY_VAL, 1);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
@Override
public StringBuffer format(Object o, @NonNull StringBuffer stringBuffer,
@NonNull FieldPosition fieldPosition) {
Number year = ((Number) o).intValue() + 2012;
stringBuffer.append(year);
return stringBuffer;
}
@Override
public Object parseObject(String s, @NonNull ParsePosition parsePosition) {
return null;
}
});
}
}
@@ -0,0 +1,252 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.os.Bundle;
import com.androidplot.Plot;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.XYSeries;
import com.androidplot.xy.*;
import java.text.DecimalFormat;
import java.util.Observable;
import java.util.Observer;
public class DynamicXYPlotActivity extends Activity {
// redraws a plot whenever an update is received:
private class MyPlotUpdater implements Observer {
Plot plot;
public MyPlotUpdater(Plot plot) {
this.plot = plot;
}
@Override
public void update(Observable o, Object arg) {
plot.redraw();
}
}
private XYPlot dynamicPlot;
private MyPlotUpdater plotUpdater;
SampleDynamicXYDatasource data;
private Thread myThread;
@Override
public void onCreate(Bundle savedInstanceState) {
// android boilerplate stuff
super.onCreate(savedInstanceState);
setContentView(R.layout.dynamic_xyplot_example);
// get handles to our View defined in layout.xml:
dynamicPlot = (XYPlot) findViewById(R.id.dynamicXYPlot);
plotUpdater = new MyPlotUpdater(dynamicPlot);
// only display whole numbers in domain labels
dynamicPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).
setFormat(new DecimalFormat("0"));
// getInstance and position datasets:
data = new SampleDynamicXYDatasource();
SampleDynamicSeries sine1Series = new SampleDynamicSeries(data, 0, "Sine 1");
SampleDynamicSeries sine2Series = new SampleDynamicSeries(data, 1, "Sine 2");
LineAndPointFormatter formatter1 = new LineAndPointFormatter(
Color.rgb(0, 200, 0), null, null, null);
formatter1.getLinePaint().setStrokeJoin(Paint.Join.ROUND);
formatter1.getLinePaint().setStrokeWidth(10);
dynamicPlot.addSeries(sine1Series,
formatter1);
LineAndPointFormatter formatter2 =
new LineAndPointFormatter(Color.rgb(0, 0, 200), null, null, null);
formatter2.getLinePaint().setStrokeWidth(10);
formatter2.getLinePaint().setStrokeJoin(Paint.Join.ROUND);
//formatter2.getFillPaint().setAlpha(220);
dynamicPlot.addSeries(sine2Series, formatter2);
// hook up the plotUpdater to the data model:
data.addObserver(plotUpdater);
// thin out domain tick labels so they dont overlap each other:
dynamicPlot.setDomainStepMode(StepMode.INCREMENT_BY_VAL);
dynamicPlot.setDomainStepValue(5);
dynamicPlot.setRangeStepMode(StepMode.INCREMENT_BY_VAL);
dynamicPlot.setRangeStepValue(10);
dynamicPlot.getGraph().getLineLabelStyle(
XYGraphWidget.Edge.LEFT).setFormat(new DecimalFormat("###.#"));
// uncomment this line to freeze the range boundaries:
dynamicPlot.setRangeBoundaries(-100, 100, BoundaryMode.FIXED);
// create a dash effect for domain and range grid lines:
DashPathEffect dashFx = new DashPathEffect(
new float[] {PixelUtils.dpToPix(3), PixelUtils.dpToPix(3)}, 0);
dynamicPlot.getGraph().getDomainGridLinePaint().setPathEffect(dashFx);
dynamicPlot.getGraph().getRangeGridLinePaint().setPathEffect(dashFx);
}
@Override
public void onResume() {
// kick off the data generating thread:
myThread = new Thread(data);
myThread.start();
super.onResume();
}
@Override
public void onPause() {
data.stopThread();
super.onPause();
}
class SampleDynamicXYDatasource implements Runnable {
// encapsulates management of the observers watching this datasource for update events:
class MyObservable extends Observable {
@Override
public void notifyObservers() {
setChanged();
super.notifyObservers();
}
}
private static final double FREQUENCY = 5; // larger is lower frequency
private static final int MAX_AMP_SEED = 100;
private static final int MIN_AMP_SEED = 10;
private static final int AMP_STEP = 1;
static final int SINE1 = 0;
static final int SINE2 = 1;
private static final int SAMPLE_SIZE = 31;
private int phase = 0;
private int sinAmp = 1;
private MyObservable notifier;
private boolean keepRunning = false;
{
notifier = new MyObservable();
}
void stopThread() {
keepRunning = false;
}
//@Override
public void run() {
try {
keepRunning = true;
boolean isRising = true;
while (keepRunning) {
Thread.sleep(10); // decrease or remove to speed up the refresh rate.
phase++;
if (sinAmp >= MAX_AMP_SEED) {
isRising = false;
} else if (sinAmp <= MIN_AMP_SEED) {
isRising = true;
}
if (isRising) {
sinAmp += AMP_STEP;
} else {
sinAmp -= AMP_STEP;
}
notifier.notifyObservers();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int getItemCount(int series) {
return SAMPLE_SIZE;
}
Number getX(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
return index;
}
Number getY(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
double angle = (index + (phase))/FREQUENCY;
double amp = sinAmp * Math.sin(angle);
switch (series) {
case SINE1:
return amp;
case SINE2:
return -amp;
default:
throw new IllegalArgumentException();
}
}
void addObserver(Observer observer) {
notifier.addObserver(observer);
}
public void removeObserver(Observer observer) {
notifier.deleteObserver(observer);
}
}
class SampleDynamicSeries implements XYSeries {
private SampleDynamicXYDatasource datasource;
private int seriesIndex;
private String title;
SampleDynamicSeries(SampleDynamicXYDatasource datasource, int seriesIndex, String title) {
this.datasource = datasource;
this.seriesIndex = seriesIndex;
this.title = title;
}
@Override
public String getTitle() {
return title;
}
@Override
public int size() {
return datasource.getItemCount(seriesIndex);
}
@Override
public Number getX(int index) {
return datasource.getX(seriesIndex, index);
}
@Override
public Number getY(int index) {
return datasource.getY(seriesIndex, index);
}
}
}
@@ -0,0 +1,211 @@
/*
* Copyright 2016 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.graphics.Paint;
import android.os.Bundle;
import com.androidplot.Plot;
import com.androidplot.util.Redrawer;
import com.androidplot.xy.*;
import java.lang.ref.*;
/**
* An example of a real-time plot displaying an asynchronously updated model of ECG data. There are three
* key items to pay attention to here:
* 1 - The model data is updated independently of all other data via a background thread. This is typical
* of most signal inputs.
*
* 2 - The main render loop is controlled by a separate thread governed by an instance of {@link Redrawer}.
* The alternative is to try synchronously invoking {@link Plot#redraw()} within whatever system is updating
* the model, which would severely degrade performance.
*
* 3 - The plot is set to render using a background thread via config attr in R.layout.ecg_example.xml.
* This ensures that the rest of the app will remain responsive during rendering.
*/
public class ECGExample extends Activity {
private XYPlot plot;
/**
* Uses a separate thread to modulate redraw frequency.
*/
private Redrawer redrawer;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.ecg_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
ECGModel ecgSeries = new ECGModel(2000, 200);
// add a new series' to the xyplot:
MyFadeFormatter formatter =new MyFadeFormatter(2000);
formatter.setLegendIconEnabled(false);
plot.addSeries(ecgSeries, formatter);
plot.setRangeBoundaries(0, 10, BoundaryMode.FIXED);
plot.setDomainBoundaries(0, 2000, BoundaryMode.FIXED);
// reduce the number of range labels
plot.setLinesPerRangeLabel(3);
// start generating ecg data in the background:
ecgSeries.start(new WeakReference<>(plot.getRenderer(AdvancedLineAndPointRenderer.class)));
// set a redraw rate of 30hz and start immediately:
redrawer = new Redrawer(plot, 30, true);
}
/**
* Special {@link AdvancedLineAndPointRenderer.Formatter} that draws a line
* that fades over time. Designed to be used in conjunction with a circular buffer model.
*/
public static class MyFadeFormatter extends AdvancedLineAndPointRenderer.Formatter {
private int trailSize;
MyFadeFormatter(int trailSize) {
this.trailSize = trailSize;
}
@Override
public Paint getLinePaint(int thisIndex, int latestIndex, int seriesSize) {
// offset from the latest index:
int offset;
if(thisIndex > latestIndex) {
offset = latestIndex + (seriesSize - thisIndex);
} else {
offset = latestIndex - thisIndex;
}
float scale = 255f / trailSize;
int alpha = (int) (255 - (offset * scale));
getLinePaint().setAlpha(alpha > 0 ? alpha : 0);
return getLinePaint();
}
}
/**
* Primitive simulation of some kind of signal. For this example,
* we'll pretend its an ecg. This class represents the data as a circular buffer;
* data is added sequentially from left to right. When the end of the buffer is reached,
* i is reset back to 0 and simulated sampling continues.
*/
public static class ECGModel implements XYSeries {
private final Number[] data;
private final long delayMs;
private final int blipInteral;
private final Thread thread;
private boolean keepRunning;
private int latestIndex;
private WeakReference<AdvancedLineAndPointRenderer> rendererRef;
/**
*
* @param size Sample size contained within this model
* @param updateFreqHz Frequency at which new samples are added to the model
*/
ECGModel(int size, int updateFreqHz) {
data = new Number[size];
for(int i = 0; i < data.length; i++) {
data[i] = 0;
}
// translate hz into delay (ms):
delayMs = 1000 / updateFreqHz;
// add 7 "blips" into the signal:
blipInteral = size / 7;
thread = new Thread(new Runnable() {
@Override
public void run() {
try {
while (keepRunning) {
if (latestIndex >= data.length) {
latestIndex = 0;
}
// generate some random data:
if (latestIndex % blipInteral == 0) {
// insert a "blip" to simulate a heartbeat:
data[latestIndex] = (Math.random() * 10) + 3;
} else {
// insert a random sample:
data[latestIndex] = Math.random() * 2;
}
if(latestIndex < data.length - 1) {
// null out the point immediately following i, to disable
// connecting i and i+1 with a line:
data[latestIndex +1] = null;
}
if(rendererRef.get() != null) {
rendererRef.get().setLatestIndex(latestIndex);
Thread.sleep(delayMs);
} else {
keepRunning = false;
}
latestIndex++;
}
} catch (InterruptedException e) {
keepRunning = false;
}
}
});
}
void start(final WeakReference<AdvancedLineAndPointRenderer> rendererRef) {
this.rendererRef = rendererRef;
keepRunning = true;
thread.start();
}
@Override
public int size() {
return data.length;
}
@Override
public Number getX(int index) {
return index;
}
@Override
public Number getY(int index) {
return data[index];
}
@Override
public String getTitle() {
return "Signal";
}
}
@Override
public void onStop() {
super.onStop();
redrawer.finish();
}
}
@@ -0,0 +1,134 @@
/*
* Copyright 2016 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.*;
import android.graphics.*;
import android.os.*;
import com.androidplot.util.*;
import com.androidplot.xy.*;
import java.text.*;
import java.util.*;
/**
* A simple XYPlot
*/
public class FXPlotExampleActivity extends Activity {
private XYPlot plot;
/**
* Custom line label renderer that highlights origin labels
*/
class MyLineLabelRenderer extends XYGraphWidget.LineLabelRenderer {
@Override
protected void drawLabel(Canvas canvas, String text, Paint paint,
float x, float y, boolean isOrigin) {
if(isOrigin) {
// make the origin labels red:
final Paint originPaint = new Paint(paint);
originPaint.setColor(Color.RED);
super.drawLabel(canvas, text, originPaint, x, y , isOrigin);
} else {
super.drawLabel(canvas, text, paint, x, y , isOrigin);
}
}
}
/**
* Draws every other tick label and renders text in gray instead of white.
*/
class MySecondaryLabelRenderer extends MyLineLabelRenderer {
@Override
public void drawLabel(Canvas canvas, XYGraphWidget.LineLabelStyle style,
Number val, float x, float y, boolean isOrigin) {
if(val.doubleValue() % 2 == 0) {
final Paint paint = style.getPaint();
if(!isOrigin) {
paint.setColor(Color.GRAY);
}
super.drawLabel(canvas, style, val, x, y, isOrigin);
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fx_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
plot.setDomainStep(StepMode.INCREMENT_BY_VAL, 1);
plot.setRangeStep(StepMode.INCREMENT_BY_VAL, 1);
plot.centerOnDomainOrigin(0);
plot.centerOnRangeOrigin(0);
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
LineAndPointFormatter series1Format =
new LineAndPointFormatter(this, R.xml.line_point_formatter);
// use our custom renderer to make origin labels red
plot.getGraph().setLineLabelRenderer(XYGraphWidget.Edge.BOTTOM, new MyLineLabelRenderer());
plot.getGraph().setLineLabelRenderer(XYGraphWidget.Edge.LEFT, new MyLineLabelRenderer());
// skip every other line for top and right edge labels
plot.getGraph().setLineLabelRenderer(XYGraphWidget.Edge.RIGHT, new MySecondaryLabelRenderer());
plot.getGraph().setLineLabelRenderer(XYGraphWidget.Edge.TOP, new MySecondaryLabelRenderer());
// don't show decimal places for top and right edge labels
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.TOP).setFormat(new DecimalFormat("0"));
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.RIGHT).setFormat(new DecimalFormat("0"));
// create a dash effect for domain and range grid lines:
DashPathEffect dashFx = new DashPathEffect(
new float[] {PixelUtils.dpToPix(3), PixelUtils.dpToPix(3)}, 0);
plot.getGraph().getDomainGridLinePaint().setPathEffect(dashFx);
plot.getGraph().getRangeGridLinePaint().setPathEffect(dashFx);
// add a new series' to the xyplot:
plot.addSeries(generateSeries(-5, 5, 100), series1Format);
}
protected XYSeries generateSeries(double minX, double maxX, double resolution) {
final double range = maxX - minX;
final double step = range / resolution;
List<Number> xVals = new ArrayList<>();
List<Number> yVals = new ArrayList<>();
double x = minX;
while (x <= maxX) {
xVals.add(x);
yVals.add(fx(x));
x +=step;
}
return new SimpleXYSeries(xVals, yVals, "f(x) = (x^2) - 13");
}
protected double fx(double x) {
return Math.abs(x*x) - 13;
}
}
@@ -0,0 +1,131 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import androidx.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.androidplot.Plot;
import com.androidplot.ui.SeriesBundle;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.CatmullRomInterpolator;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ListViewActivity extends Activity {
private static final int NUM_PLOTS = 10;
private static final int NUM_POINTS_PER_SERIES = 10;
private static final int NUM_SERIES_PER_PLOT = 5;
private ListView lv;
private List<List<SeriesBundle<XYSeries, LineAndPointFormatter>>> seriesData = new ArrayList<>(NUM_PLOTS);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_example);
PixelUtils.init(this);
generateData();
lv = (ListView) findViewById(R.id.listView1);
lv.setAdapter(new MyViewAdapter(getApplicationContext(), R.layout.listview_example_item, null));
}
protected void generateData() {
Random generator = new Random();
for(int i = 0; i < NUM_PLOTS; i++) {
List<SeriesBundle<XYSeries, LineAndPointFormatter>> seriesList
= new ArrayList<>(NUM_SERIES_PER_PLOT);
for (int k = 0; k < NUM_SERIES_PER_PLOT; k++) {
ArrayList<Number> nums = new ArrayList<>();
for (int j = 0; j < NUM_POINTS_PER_SERIES; j++) {
nums.add(generator.nextFloat());
}
double rl = Math.random();
double gl = Math.random();
double bl = Math.random();
double rp = Math.random();
double gp = Math.random();
double bp = Math.random();
LineAndPointFormatter lpf = new LineAndPointFormatter(
Color.rgb(Double.valueOf(rl * 255).intValue(),
Double.valueOf(gl * 255).intValue(), Double.valueOf(bl * 255).intValue()),
Color.rgb(Double.valueOf(rp * 255).intValue(),
Double.valueOf(gp * 255).intValue(), Double.valueOf(bp * 255).intValue()),
null, null);
// for fun, configure interpolation on the formatter:
lpf.setInterpolationParams(
new CatmullRomInterpolator.Params(20, CatmullRomInterpolator.Type.Centripetal));
seriesList.add(new SeriesBundle<XYSeries, LineAndPointFormatter>(
new SimpleXYSeries(nums, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "S" + k),
lpf));
}
seriesData.add(seriesList);
}
}
class MyViewAdapter extends ArrayAdapter<View> {
public MyViewAdapter(Context context, int resId, List<View> views) {
super(context, resId, views);
}
@Override
public int getCount() {
return NUM_PLOTS;
}
@NonNull
@Override
public View getView(int pos, View convertView, @NonNull ViewGroup parent) {
LayoutInflater inf = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = convertView;
if (v == null) {
v = inf.inflate(R.layout.listview_example_item, parent, false);
}
Plot p = (XYPlot) v.findViewById(R.id.xyplot);
p.clear();
p.getTitle().setText("plot" + pos);
List<SeriesBundle<XYSeries, LineAndPointFormatter>> thisSeriesList = seriesData.get(pos);
for(SeriesBundle<XYSeries, LineAndPointFormatter> sf : thisSeriesList) {
p.addSeries(sf.getSeries(), sf.getFormatter());
}
p.redraw();
return v;
}
}
}
@@ -0,0 +1,109 @@
/*
* Copyright 2021 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos
import android.app.Activity
import android.os.Bundle
import android.content.Intent
import com.androidplot.demos.databinding.MainBinding
class MainActivity : Activity() {
private lateinit var binding: MainBinding
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = MainBinding.inflate(layoutInflater)
binding.animatedXYPlotExButton.setOnClickListener {
startActivity(Intent(this, AnimatedXYPlotActivity::class.java))
}
binding.startScatterExButton.setOnClickListener {
startActivity(Intent(this, ScatterPlotActivity::class.java))
}
binding.startSimplePieExButton.setOnClickListener {
startActivity(Intent(this, SimplePieChartActivity::class.java))
}
binding.startDynamicXYExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, DynamicXYPlotActivity::class.java))
}
binding.startCandlestickExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, CandlestickChartActivity::class.java))
}
binding.startSimpleXYExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, SimpleXYPlotActivity::class.java))
}
binding.startBarPlotExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, BarPlotExampleActivity::class.java))
}
binding.startOrSensorExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, OrientationSensorExampleActivity::class.java))
}
binding.startDualScaleExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, DualScaleActivity::class.java))
}
binding.startTimeSeriesExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, TimeSeriesActivity::class.java))
}
binding.startStepChartExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, StepChartExampleActivity::class.java))
}
binding.startScrollZoomButton.setOnClickListener {
startActivity(Intent(this@MainActivity, TouchZoomExampleActivity::class.java))
}
binding.startXyRegionExampleButton.setOnClickListener {
startActivity(Intent(this@MainActivity, XYRegionExampleActivity::class.java))
}
binding.startXyListViewExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, ListViewActivity::class.java))
}
binding.startXyRecyclerViewExButton.setOnClickListener {
startActivity(Intent(this@MainActivity, RecyclerViewActivity::class.java))
}
binding.startXYPlotWithBgImgExample.setOnClickListener {
startActivity(Intent(this@MainActivity, XYPlotWithBgImgActivity::class.java))
}
binding.startECGExample.setOnClickListener {
startActivity(Intent(this@MainActivity, ECGExample::class.java))
}
binding.fxPlotExample.setOnClickListener {
startActivity(Intent(this@MainActivity, FXPlotExampleActivity::class.java))
}
binding.bubbleChartExample.setOnClickListener {
startActivity(Intent(this@MainActivity, BubbleChartActivity::class.java))
}
setContentView(binding.root)
}
}
@@ -0,0 +1,251 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.content.Context;
import android.graphics.*;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import com.androidplot.Plot;
import com.androidplot.util.PixelUtils;
import com.androidplot.util.PlotStatistics;
import com.androidplot.util.Redrawer;
import com.androidplot.xy.*;
import java.text.DecimalFormat;
import java.util.Arrays;
// Monitor the phone's orientation sensor and plot the resulting azimuth pitch and roll values.
// See: http://developer.android.com/reference/android/hardware/SensorEvent.html
public class OrientationSensorExampleActivity extends Activity implements SensorEventListener
{
private static final int HISTORY_SIZE = 1000;
private SensorManager sensorMgr = null;
private Sensor orSensor = null;
private XYPlot aprLevelsPlot = null;
private XYPlot aprHistoryPlot = null;
private CheckBox hwAcceleratedCb;
private CheckBox showFpsCb;
private SimpleXYSeries aLvlSeries;
private SimpleXYSeries pLvlSeries;
private SimpleXYSeries rLvlSeries;
private SimpleXYSeries azimuthHistorySeries = null;
private SimpleXYSeries pitchHistorySeries = null;
private SimpleXYSeries rollHistorySeries = null;
private Redrawer redrawer;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.orientation_sensor_example);
// setup the APR Levels plot:
aprLevelsPlot = (XYPlot) findViewById(R.id.aprLevelsPlot);
aprLevelsPlot.setDomainBoundaries(-1, 1, BoundaryMode.FIXED);
aLvlSeries = new SimpleXYSeries("A");
pLvlSeries = new SimpleXYSeries("P");
rLvlSeries = new SimpleXYSeries("R");
aprLevelsPlot.addSeries(aLvlSeries,
new BarFormatter(Color.rgb(0, 200, 0), Color.rgb(0, 80, 0)));
aprLevelsPlot.addSeries(pLvlSeries,
new BarFormatter(Color.rgb(200, 0, 0), Color.rgb(0, 80, 0)));
aprLevelsPlot.addSeries(rLvlSeries,
new BarFormatter(Color.rgb(0, 0, 200), Color.rgb(0, 80, 0)));
aprLevelsPlot.setDomainStepValue(3);
aprLevelsPlot.setLinesPerRangeLabel(3);
// per the android documentation, the minimum and maximum readings we can get from
// any of the orientation sensors is -180 and 359 respectively so we will fix our plot's
// boundaries to those values. If we did not do this, the plot would auto-range which
// can be visually confusing in the case of dynamic plots.
aprLevelsPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED);
// update our domain and range axis labels:
aprLevelsPlot.setDomainLabel("");
aprLevelsPlot.getDomainTitle().pack();
aprLevelsPlot.setRangeLabel("Angle (Degs)");
aprLevelsPlot.getRangeTitle().pack();
aprLevelsPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).
setFormat(new DecimalFormat("#"));
// setup the APR History plot:
aprHistoryPlot = (XYPlot) findViewById(R.id.aprHistoryPlot);
azimuthHistorySeries = new SimpleXYSeries("Az.");
azimuthHistorySeries.useImplicitXVals();
pitchHistorySeries = new SimpleXYSeries("Pitch");
pitchHistorySeries.useImplicitXVals();
rollHistorySeries = new SimpleXYSeries("Roll");
rollHistorySeries.useImplicitXVals();
aprHistoryPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED);
aprHistoryPlot.setDomainBoundaries(0, HISTORY_SIZE, BoundaryMode.FIXED);
aprHistoryPlot.addSeries(azimuthHistorySeries,
new LineAndPointFormatter(
Color.rgb(100, 100, 200), null, null, null));
aprHistoryPlot.addSeries(pitchHistorySeries,
new LineAndPointFormatter(
Color.rgb(100, 200, 100), null, null, null));
aprHistoryPlot.addSeries(rollHistorySeries,
new LineAndPointFormatter(
Color.rgb(200, 100, 100), null, null, null));
aprHistoryPlot.setDomainStepMode(StepMode.INCREMENT_BY_VAL);
aprHistoryPlot.setDomainStepValue(HISTORY_SIZE/10);
aprHistoryPlot.setLinesPerRangeLabel(3);
aprHistoryPlot.setDomainLabel("Sample Index");
aprHistoryPlot.getDomainTitle().pack();
aprHistoryPlot.setRangeLabel("Angle (Degs)");
aprHistoryPlot.getRangeTitle().pack();
aprHistoryPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).
setFormat(new DecimalFormat("#"));
aprHistoryPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).
setFormat(new DecimalFormat("#"));
// setup checkboxes:
hwAcceleratedCb = (CheckBox) findViewById(R.id.hwAccelerationCb);
final PlotStatistics levelStats = new PlotStatistics(1000, false);
final PlotStatistics histStats = new PlotStatistics(1000, false);
aprLevelsPlot.addListener(levelStats);
aprHistoryPlot.addListener(histStats);
hwAcceleratedCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b) {
aprLevelsPlot.setLayerType(View.LAYER_TYPE_NONE, null);
aprHistoryPlot.setLayerType(View.LAYER_TYPE_NONE, null);
} else {
aprLevelsPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
aprHistoryPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
}
});
showFpsCb = (CheckBox) findViewById(R.id.showFpsCb);
showFpsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
levelStats.setAnnotatePlotEnabled(b);
histStats.setAnnotatePlotEnabled(b);
}
});
// get a ref to the BarRenderer so we can make some changes to it:
BarRenderer barRenderer = aprLevelsPlot.getRenderer(BarRenderer.class);
if(barRenderer != null) {
// make our bars a little thicker than the default so they can be seen better:
barRenderer.setBarGroupWidth(
BarRenderer.BarGroupWidthMode.FIXED_WIDTH, PixelUtils.dpToPix(18));
}
// register for orientation sensor events:
sensorMgr = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
for (Sensor sensor : sensorMgr.getSensorList(Sensor.TYPE_ORIENTATION)) {
if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
orSensor = sensor;
}
}
// if we can't access the orientation sensor then exit:
if (orSensor == null) {
System.out.println("Failed to attach to orSensor.");
cleanup();
}
sensorMgr.registerListener(this, orSensor, SensorManager.SENSOR_DELAY_UI);
redrawer = new Redrawer(
Arrays.asList(new Plot[]{aprHistoryPlot, aprLevelsPlot}),
100, false);
}
@Override
public void onResume() {
super.onResume();
redrawer.start();
}
@Override
public void onPause() {
redrawer.pause();
super.onPause();
}
@Override
public void onDestroy() {
redrawer.finish();
super.onDestroy();
}
private void cleanup() {
// aunregister with the orientation sensor before exiting:
sensorMgr.unregisterListener(this);
finish();
}
// Called whenever a new orSensor reading is taken.
@Override
public synchronized void onSensorChanged(SensorEvent sensorEvent) {
// update level data:
aLvlSeries.setModel(Arrays.asList(
new Number[]{sensorEvent.values[0]}),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
pLvlSeries.setModel(Arrays.asList(
new Number[]{sensorEvent.values[1]}),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
rLvlSeries.setModel(Arrays.asList(
new Number[]{sensorEvent.values[2]}),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
// get rid the oldest sample in history:
if (rollHistorySeries.size() > HISTORY_SIZE) {
rollHistorySeries.removeFirst();
pitchHistorySeries.removeFirst();
azimuthHistorySeries.removeFirst();
}
// add the latest history sample:
azimuthHistorySeries.addLast(null, sensorEvent.values[0]);
pitchHistorySeries.addLast(null, sensorEvent.values[1]);
rollHistorySeries.addLast(null, sensorEvent.values[2]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
// Not interested in this event
}
}
@@ -0,0 +1,130 @@
/*
* Copyright 2021 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos
import android.app.Activity
import android.graphics.Color
import com.androidplot.ui.SeriesBundle
import android.os.Bundle
import android.view.ViewGroup
import android.view.LayoutInflater
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.androidplot.demos.databinding.RecyclerviewExampleBinding
import com.androidplot.demos.databinding.RecyclerviewExampleItemBinding
import com.androidplot.util.PixelUtils
import com.androidplot.xy.*
import java.util.*
class RecyclerViewActivity : Activity() {
private lateinit var binding: RecyclerviewExampleBinding
companion object {
private const val NUM_PLOTS = 10
private const val NUM_POINTS_PER_SERIES = 10
private const val NUM_SERIES_PER_PLOT = 5
}
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
PixelUtils.init(this)
binding = RecyclerviewExampleBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.recyclerView.setHasFixedSize(true)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = MyRecyclerViewAdapter()
}
class MyRecyclerViewHolder(
private val binding: RecyclerviewExampleItemBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(data: List<SeriesBundle<XYSeries, LineAndPointFormatter>>, title: String) {
val plot = binding.plot
plot.clear()
plot.title.text = title
data.map { plot.addSeries(it.series, it.formatter) }
plot.redraw()
}
}
class MyRecyclerViewAdapter : RecyclerView.Adapter<MyRecyclerViewHolder>() {
private val seriesData = generateData()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRecyclerViewHolder {
val itemBinding = RecyclerviewExampleItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MyRecyclerViewHolder(itemBinding)
}
override fun onBindViewHolder(holder: MyRecyclerViewHolder, position: Int) {
holder.bind(seriesData[position], "Series $position")
}
override fun getItemCount() = seriesData.size
private fun generateData(): List<List<SeriesBundle<XYSeries, LineAndPointFormatter>>> {
val theData = mutableListOf<List<SeriesBundle<XYSeries, LineAndPointFormatter>>>()
fun generateBundle(seriesLabel: String): SeriesBundle<XYSeries, LineAndPointFormatter> {
val generator = Random()
val nums = ArrayList<Number>()
for (j in 0 until NUM_POINTS_PER_SERIES) {
nums.add(generator.nextFloat())
}
val formatter = LineAndPointFormatter(
Color.rgb(
java.lang.Double.valueOf(Math.random() * 255).toInt(),
java.lang.Double.valueOf(Math.random() * 255).toInt(),
java.lang.Double.valueOf(Math.random() * 255).toInt()
),
Color.rgb(
java.lang.Double.valueOf(Math.random() * 255).toInt(),
java.lang.Double.valueOf(Math.random() * 255).toInt(),
java.lang.Double.valueOf(Math.random() * 255).toInt()
),
null, null
)
// for fun, configure interpolation on the formatter:
formatter.interpolationParams = CatmullRomInterpolator.Params(
20,
CatmullRomInterpolator.Type.Centripetal
)
return SeriesBundle(
SimpleXYSeries(
nums,
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY,
seriesLabel
),
formatter
)
}
for (i in 0 until NUM_PLOTS) {
val seriesList: MutableList<SeriesBundle<XYSeries, LineAndPointFormatter>> =
ArrayList(NUM_SERIES_PER_PLOT)
for (k in 0 until NUM_SERIES_PER_PLOT) {
seriesList.add(generateBundle("S$k"))
}
theData.add(seriesList)
}
return theData
}
}
}
@@ -0,0 +1,79 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.os.Bundle;
import com.androidplot.xy.*;
/**
* A scatter plot
*/
public class ScatterPlotActivity extends Activity
{
private XYPlot plot;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.scatter_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
XYSeries series1 = generateScatter("series1", 80, new RectRegion(10, 50, 10, 50));
XYSeries series2 = generateScatter("series2", 80, new RectRegion(30, 70, 30, 70));
plot.setDomainBoundaries(0, 80, BoundaryMode.FIXED);
plot.setRangeBoundaries(0, 80, BoundaryMode.FIXED);
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
LineAndPointFormatter series1Format =
new LineAndPointFormatter(this, R.xml.point_formatter);
LineAndPointFormatter series2Format =
new LineAndPointFormatter(this, R.xml.point_formatter_2);
// add each series to the xyplot:
plot.addSeries(series1, series1Format);
plot.addSeries(series2, series2Format);
// reduce the number of range labels
plot.setLinesPerRangeLabel(3);
}
/**
* Generate a XYSeries of random points within a specified region
* @param title
* @param numPoints
* @param region
* @return
*/
private XYSeries generateScatter(String title, int numPoints, RectRegion region) {
SimpleXYSeries series = new SimpleXYSeries(title);
for(int i = 0; i < numPoints; i++) {
series.addLast(
region.getMinX().doubleValue() + (Math.random() * region.getWidth().doubleValue()),
region.getMinY().doubleValue() + (Math.random() * region.getHeight().doubleValue())
);
}
return series;
}
}
@@ -0,0 +1,200 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.*;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.SeekBar;
import android.widget.TextView;
import com.androidplot.pie.PieChart;
import com.androidplot.pie.PieRenderer;
import com.androidplot.pie.Segment;
import com.androidplot.pie.SegmentFormatter;
import com.androidplot.util.*;
import java.util.*;
/**
* The simplest possible example of using AndroidPlot to plot some data.
*/
public class SimplePieChartActivity extends Activity
{
public static final int SELECTED_SEGMENT_OFFSET = 50;
private TextView donutSizeTextView;
private SeekBar donutSizeSeekBar;
public PieChart pie;
private Segment s1;
private Segment s2;
private Segment s3;
private Segment s4;
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.pie_chart);
// initialize our XYPlot reference:
pie = (PieChart) findViewById(R.id.mySimplePieChart);
// enable the legend:
pie.getLegend().setVisible(true);
final float padding = PixelUtils.dpToPix(30);
pie.getPie().setPadding(padding, padding, padding, padding);
// detect segment clicks:
pie.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
PointF click = new PointF(motionEvent.getX(), motionEvent.getY());
if(pie.getPie().containsPoint(click)) {
Segment segment = pie.getRenderer(PieRenderer.class).getContainingSegment(click);
if(segment != null) {
final boolean isSelected = getFormatter(segment).getOffset() != 0;
deselectAll();
setSelected(segment, !isSelected);
pie.redraw();
}
}
return false;
}
private SegmentFormatter getFormatter(Segment segment) {
return pie.getFormatter(segment, PieRenderer.class);
}
private void deselectAll() {
List<Segment> segments = pie.getRegistry().getSeriesList();
for(Segment segment : segments) {
setSelected(segment, false);
}
}
private void setSelected(Segment segment, boolean isSelected) {
SegmentFormatter f = getFormatter(segment);
if(isSelected) {
f.setOffset(SELECTED_SEGMENT_OFFSET);
} else {
f.setOffset(0);
}
}
});
donutSizeSeekBar = (SeekBar) findViewById(R.id.donutSizeSeekBar);
donutSizeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
pie.getRenderer(PieRenderer.class).setDonutSize(seekBar.getProgress()/100f,
PieRenderer.DonutMode.PERCENT);
pie.redraw();
updateDonutText();
}
});
donutSizeTextView = (TextView) findViewById(R.id.donutSizeTextView);
updateDonutText();
s1 = new Segment("s1", 3);
s2 = new Segment("s2", 1);
s3 = new Segment("s3", 7);
s4 = new Segment("s4", 9);
EmbossMaskFilter emf = new EmbossMaskFilter(
new float[]{1, 1, 1}, 0.4f, 10, 8.2f);
SegmentFormatter sf1 = new SegmentFormatter(this, R.xml.pie_segment_formatter1);
sf1.getLabelPaint().setShadowLayer(3, 0, 0, Color.BLACK);
sf1.getFillPaint().setMaskFilter(emf);
SegmentFormatter sf2 = new SegmentFormatter(this, R.xml.pie_segment_formatter2);
sf2.getLabelPaint().setShadowLayer(3, 0, 0, Color.BLACK);
sf2.getFillPaint().setMaskFilter(emf);
SegmentFormatter sf3 = new SegmentFormatter(this, R.xml.pie_segment_formatter3);
sf3.getLabelPaint().setShadowLayer(3, 0, 0, Color.BLACK);
sf3.getFillPaint().setMaskFilter(emf);
SegmentFormatter sf4 = new SegmentFormatter(this, R.xml.pie_segment_formatter4);
sf4.getLabelPaint().setShadowLayer(3, 0, 0, Color.BLACK);
sf4.getFillPaint().setMaskFilter(emf);
pie.addSegment(s1, sf1);
pie.addSegment(s2, sf2);
pie.addSegment(s3, sf3);
pie.addSegment(s4, sf4);
pie.getBorderPaint().setColor(Color.TRANSPARENT);
pie.getBackgroundPaint().setColor(Color.TRANSPARENT);
}
@Override
public void onStart() {
super.onStart();
setupIntroAnimation();
}
protected void updateDonutText() {
donutSizeTextView.setText(donutSizeSeekBar.getProgress() + "%");
}
protected void setupIntroAnimation() {
final PieRenderer renderer = pie.getRenderer(PieRenderer.class);
// start with a zero degrees pie:
renderer.setExtentDegs(0);
// animate a scale value from a starting val of 0 to a final value of 1:
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
// use an animation pattern that begins and ends slowly:
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float scale = valueAnimator.getAnimatedFraction();
renderer.setExtentDegs(360 * scale);
pie.redraw();
}
});
// the animation will run for 1.5 seconds:
animator.setDuration(1500);
animator.start();
}
}
@@ -0,0 +1,104 @@
/*
* Copyright 2018 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.graphics.DashPathEffect;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.CatmullRomInterpolator;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Arrays;
/**
* A simple XYPlot
*/
public class SimpleXYPlotActivity extends Activity {
private XYPlot plot;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_xy_plot_example);
// initialize our XYPlot reference:
plot = findViewById(R.id.plot);
// create a couple arrays of y-values to plot:
final Number[] domainLabels = {1, 2, 3, 6, 7, 8, 9, 10, 13, 14};
Number[] series1Numbers = {1, 4, 2, 8, 4, 16, 8, 32, 16, 64};
Number[] series2Numbers = {5, 2, 10, 5, 20, 10, 40, 20, 80, 40};
// turn the above arrays into XYSeries':
// (Y_VALS_ONLY means use the element index as the x value)
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series1");
XYSeries series2 = new SimpleXYSeries(
Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
LineAndPointFormatter series1Format =
new LineAndPointFormatter(this, R.xml.line_point_formatter_with_labels);
LineAndPointFormatter series2Format =
new LineAndPointFormatter(this, R.xml.line_point_formatter_with_labels_2);
// add an "dash" effect to the series2 line:
series2Format.getLinePaint().setPathEffect(new DashPathEffect(new float[] {
// always use DP when specifying pixel sizes, to keep things consistent across devices:
PixelUtils.dpToPix(20),
PixelUtils.dpToPix(15)}, 0));
// (optional) add some smoothing to the lines:
// see: http://androidplot.com/smooth-curves-and-androidplot/
series1Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
series2Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
// add a new series' to the xyplot:
plot.addSeries(series1, series1Format);
plot.addSeries(series2, series2Format);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
@Override
public StringBuffer format(Object obj, @NonNull StringBuffer toAppendTo, @NonNull FieldPosition pos) {
int i = Math.round(((Number) obj).floatValue());
return toAppendTo.append(domainLabels[i]);
}
@Override
public Object parseObject(String source, @NonNull ParsePosition pos) {
return null;
}
});
}
}
@@ -0,0 +1,122 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.StepFormatter;
import com.androidplot.xy.StepMode;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Arrays;
public class StepChartExampleActivity extends Activity
{
private XYPlot mySimpleXYPlot;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.step_chart_example);
// initialize our XYPlot reference:
mySimpleXYPlot = (XYPlot) findViewById(R.id.stepChartExamplePlot);
// y-vals to plot:
Number[] series1Numbers = {1, 2, 3, 4, 2, 3, 4, 2, 2, 2, 3, 4, 2, 3, 2, 2};
// create our series from our array of nums:
XYSeries series2 = new SimpleXYSeries(
Arrays.asList(series1Numbers),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY,
"Thread #1");
final int screenHeightPx = getWindowManager().getDefaultDisplay().getHeight();
// setup our line fill paint to be a slightly transparent gradient:
Paint lineFill = new Paint();
lineFill.setAlpha(200);
lineFill.setShader(new LinearGradient(0, 0, 0, screenHeightPx, Color.WHITE, Color.BLUE, Shader.TileMode.MIRROR));
StepFormatter stepFormatter = new StepFormatter(Color.WHITE, Color.BLUE);
stepFormatter.setVertexPaint(null); // don't draw individual points
stepFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(3));
stepFormatter.getLinePaint().setAntiAlias(false);
stepFormatter.setFillPaint(lineFill);
mySimpleXYPlot.addSeries(series2, stepFormatter);
// adjust the domain/range ticks to make more sense; label per line for range and label per 5 ticks domain:
mySimpleXYPlot.setRangeStep(StepMode.INCREMENT_BY_VAL, 1);
mySimpleXYPlot.setDomainStep(StepMode.INCREMENT_BY_VAL, 1);
mySimpleXYPlot.setLinesPerRangeLabel(1);
mySimpleXYPlot.setLinesPerDomainLabel(5);
// get rid of decimal points in our domain labels:
mySimpleXYPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).
setFormat(new DecimalFormat("0"));
// create a custom getFormatter to draw our state names as range tick labels:
mySimpleXYPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).setFormat(new Format() {
@Override
public StringBuffer format(Object obj, @NonNull StringBuffer toAppendTo,
@NonNull FieldPosition pos) {
Number num = (Number) obj;
switch (num.intValue()) {
case 1:
toAppendTo.append("Init");
break;
case 2:
toAppendTo.append("Idle");
break;
case 3:
toAppendTo.append("Recv");
break;
case 4:
toAppendTo.append("Send");
break;
default:
toAppendTo.append("Unknown");
break;
}
return toAppendTo;
}
@Override
public Object parseObject(String source, @NonNull ParsePosition pos) {
return null;
}
});
}
}
@@ -0,0 +1,167 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.StepMode;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class TimeSeriesActivity extends Activity {
private static final String SERIES_TITLE = "Signthings in USA";
private XYPlot plot1;
private SimpleXYSeries series;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.time_series_example);
plot1 = (XYPlot) findViewById(R.id.plot1);
// these will be our domain index labels:
final Date[] years = {
new GregorianCalendar(2001, Calendar.JANUARY, 1).getTime(),
new GregorianCalendar(2001, Calendar.JULY, 1).getTime(),
new GregorianCalendar(2002, Calendar.JANUARY, 1).getTime(),
new GregorianCalendar(2002, Calendar.JULY, 1).getTime(),
new GregorianCalendar(2003, Calendar.JANUARY, 1).getTime(),
new GregorianCalendar(2003, Calendar.JULY, 1).getTime(),
new GregorianCalendar(2004, Calendar.JANUARY, 1).getTime(),
new GregorianCalendar(2004, Calendar.JULY, 1).getTime(),
new GregorianCalendar(2005, Calendar.JANUARY, 1).getTime(),
new GregorianCalendar(2005, Calendar.JULY, 1).getTime()
};
addSeries(savedInstanceState);
plot1.setRangeBoundaries(0, 10, BoundaryMode.FIXED);
plot1.getGraph().getGridBackgroundPaint().setColor(Color.WHITE);
plot1.getGraph().getDomainGridLinePaint().setColor(Color.BLACK);
plot1.getGraph().getDomainGridLinePaint().
setPathEffect(new DashPathEffect(new float[]{1, 1}, 1));
plot1.getGraph().getRangeGridLinePaint().setColor(Color.BLACK);
plot1.getGraph().getRangeGridLinePaint().
setPathEffect(new DashPathEffect(new float[]{1, 1}, 1));
plot1.getGraph().getDomainOriginLinePaint().setColor(Color.BLACK);
plot1.getGraph().getRangeOriginLinePaint().setColor(Color.BLACK);
plot1.getGraph().setPaddingRight(2);
// draw a domain tick for each year:
plot1.setDomainStep(StepMode.SUBDIVIDE, years.length);
// customize our domain/range labels
plot1.setDomainLabel("Year");
plot1.setRangeLabel("# of Sightings");
// get rid of decimal points in our range labels:
plot1.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).
setFormat(new DecimalFormat("0.0"));
plot1.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).
setFormat(new Format() {
// create a simple date format that draws on the year portion of our timestamp.
// see http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html
// for a full description of SimpleDateFormat.
@SuppressLint("SimpleDateFormat")
private final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM yyyy");
@Override
public StringBuffer format(Object obj,
@NonNull StringBuffer toAppendTo,
@NonNull FieldPosition pos) {
// this rounding is necessary to avoid precision loss when converting from
// double back to int:
int yearIndex = (int) Math.round(((Number) obj).doubleValue());
return dateFormat.format(years[yearIndex], toAppendTo, pos);
}
@Override
public Object parseObject(String source, @NonNull ParsePosition pos) {
return null;
}
});
}
/**
* Instantiates our XYSeries, checking the current savedInstanceState for existing series data
* to avoid having to regenerate on each resume. If your series data is small and easy to
* regenerate (as it is here) then you can skip saving/restoring your series data to
* savedInstanceState.
* @param savedInstanceState Current saved instance state, if any; may be null.
*/
private void addSeries(Bundle savedInstanceState) {
Number[] yVals;
if(savedInstanceState != null) {
yVals = (Number[]) savedInstanceState.getSerializable(SERIES_TITLE);
} else {
yVals = new Number[]{5, 8, 6, 9, 3, 8, 5, 4, 7, 4};
}
// create our series from our array of nums:
series = new SimpleXYSeries(Arrays.asList(yVals),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, SERIES_TITLE);
LineAndPointFormatter formatter =
new LineAndPointFormatter(Color.rgb(0, 0, 0), Color.RED, Color.RED, null);
formatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(10));
formatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(5));
// setup our line fill paint to be a slightly transparent gradient:
Paint lineFill = new Paint();
lineFill.setAlpha(200);
formatter.setFillPaint(lineFill);
plot1.addSeries(series, formatter);
}
@Override
public void onSaveInstanceState(Bundle bundle) {
// persist our series data so we don't have to regenerate each time:
bundle.putSerializable(SERIES_TITLE, series.getyVals().toArray(new Number[]{}));
}
}
@@ -0,0 +1,186 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import java.text.DecimalFormat;
import java.util.Random;
import android.app.*;
import android.graphics.Color;
import android.os.*;
import android.view.*;
import android.widget.*;
import com.androidplot.Plot;
import com.androidplot.xy.*;
public class TouchZoomExampleActivity extends Activity {
private static final int SERIES_SIZE = 3000;
private static final int SERIES_ALPHA = 255;
private static final int NUM_GRIDLINES = 5;
private XYPlot plot;
private PanZoom panZoom;
private Button resetButton;
private Spinner panSpinner;
private Spinner zoomSpinner;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.touch_zoom_example);
resetButton = findViewById(R.id.resetButton);
resetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
reset();
}
});
plot = findViewById(R.id.plot);
// set a fixed origin and a "by-value" step mode so that grid lines will
// move dynamically with the data when the users pans or zooms:
plot.setUserDomainOrigin(0);
plot.setUserRangeOrigin(0);
// predefine the stepping of both axis
// increment will be chosen from list to best fit NUM_GRIDLINES grid lines
double[] inc_domain = new double[]{10,50,100,500};
double[] inc_range = new double[]{1,5,10,20,50,100};
plot.setDomainStepModel(new StepModelFit(plot.getBounds().getxRegion(),inc_domain,NUM_GRIDLINES));
plot.setRangeStepModel( new StepModelFit(plot.getBounds().getyRegion(),inc_range,NUM_GRIDLINES));
panSpinner = findViewById(R.id.pan_spinner);
zoomSpinner = findViewById(R.id.zoom_spinner);
plot.getGraph().setLinesPerRangeLabel(2);
plot.getGraph().setLinesPerDomainLabel(2);
plot.getGraph().getBackgroundPaint().setColor(Color.TRANSPARENT);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).
setFormat(new DecimalFormat("#####"));
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).
setFormat(new DecimalFormat("#####.#"));
plot.setRangeLabel("");
plot.setDomainLabel("");
plot.setBorderStyle(Plot.BorderStyle.NONE, null, null);
panZoom = PanZoom.attach(plot, PanZoom.Pan.BOTH, PanZoom.Zoom.STRETCH_BOTH, PanZoom.ZoomLimit.MIN_TICKS);
plot.getOuterLimits().set(0, 3000, 0, 1000);
initSpinners();
// enable autoselect of sampling level based on visible boundaries:
plot.getRegistry().setEstimator(new ZoomEstimator());
generateSeriesData();
reset();
}
private void reset() {
plot.setDomainBoundaries(0, 10000, BoundaryMode.FIXED);
plot.setRangeBoundaries(0, 1000, BoundaryMode.FIXED);
plot.redraw();
}
private ProgressDialog progress;
private void generateSeriesData() {
progress = ProgressDialog.show(this, "Loading", "Please wait...", true);
new AsyncTask() {
@Override
protected Object doInBackground(Object[] objects) {
generateAndAddSeries(625, new LineAndPointFormatter(Color.rgb(50, 0, 0), null,
Color.argb(SERIES_ALPHA, 100, 0, 0), null));
generateAndAddSeries(125, new LineAndPointFormatter(Color.rgb(50, 50, 0), null,
Color.argb(SERIES_ALPHA, 100, 100, 0), null));
generateAndAddSeries(25, new LineAndPointFormatter(Color.rgb(0, 50, 0), null,
Color.argb(SERIES_ALPHA, 0, 100, 0), null));
generateAndAddSeries(5, new LineAndPointFormatter(Color.rgb(0, 0, 0), null,
Color.argb(SERIES_ALPHA, 0, 0, 150), null));
return null;
}
@Override
protected void onPostExecute(Object result) {
progress.dismiss();
plot.redraw();
}
}.execute();
}
private void generateAndAddSeries(int max, LineAndPointFormatter formatter) {
final FixedSizeEditableXYSeries series = new FixedSizeEditableXYSeries("s" + max, SERIES_SIZE);
Random r = new Random();
for(int i = 0; i < SERIES_SIZE; i++) {
series.setX(i, i);
series.setY(r.nextInt(max), i);
}
// wrap our series in a SampledXYSeries with a threshold of 1000.
final SampledXYSeries sampledSeries =
new SampledXYSeries(series, OrderedXYSeries.XOrder.ASCENDING, 2,100);
plot.addSeries(sampledSeries, formatter);
}
private void initSpinners() {
panSpinner.setAdapter(
new ArrayAdapter<>(this, R.layout.spinner_item, PanZoom.Pan.values()));
panSpinner.setSelection(panZoom.getPan().ordinal());
panSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
panZoom.setPan(PanZoom.Pan.values()[position]);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// nothing to do
}
});
zoomSpinner.setAdapter(
new ArrayAdapter<>(this, R.layout.spinner_item, PanZoom.Zoom.values()));
zoomSpinner.setSelection(panZoom.getZoom().ordinal());
zoomSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
panZoom.setZoom(PanZoom.Zoom.values()[position]);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// nothing to do
}
});
}
// (optional) save the current pan/zoom state
@Override
public void onSaveInstanceState(Bundle bundle) {
bundle.putSerializable("pan-zoom-state", panZoom.getState());
}
// (optional) restore the previously saved pan/zoom state
@Override
public void onRestoreInstanceState(Bundle bundle) {
PanZoom.State state = (PanZoom.State) bundle.getSerializable("pan-zoom-state");
panZoom.setState(state);
plot.redraw();
}
}
@@ -0,0 +1,17 @@
package com.androidplot.demos;
import android.app.*;
import android.content.*;
/**
* Created by halfhp on 10/29/16.
*/
public class Util {
public ProgressDialog showLoadingDialog(Context context) {
return ProgressDialog.show(context, "Loading", "Please wait...", true);
}
}
@@ -0,0 +1,124 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.graphics.*;
import android.os.Bundle;
import android.view.View;
import android.widget.ToggleButton;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.*;
import java.text.DecimalFormat;
import java.util.Arrays;
public class XYPlotWithBgImgActivity extends Activity {
private static final String TAG = XYPlotWithBgImgActivity.class.getName();
private int SERIES_LEN = 50;
private Shader WHITE_SHADER = new LinearGradient(1, 1, 1, 1, Color.WHITE, Color.WHITE, Shader.TileMode.REPEAT);
private XYPlot plot;
private SimpleXYSeries series;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xy_plot_with_bq_img_example);
plot = (XYPlot) findViewById(R.id.graph_metrics);
// Format Graph
plot.getGraph().getBackgroundPaint().setColor(Color.TRANSPARENT);
plot.getGraph().getGridBackgroundPaint().setShader(WHITE_SHADER);
plot.getGraph().getDomainGridLinePaint().setColor(Color.BLACK);
plot.getGraph().getDomainGridLinePaint().setPathEffect(new DashPathEffect(new float[]{3, 3}, 1));
plot.getGraph().getRangeGridLinePaint().setColor(Color.BLACK);
plot.getGraph().getRangeGridLinePaint().setPathEffect(new DashPathEffect(new float[]{3, 3}, 1));
plot.getGraph().getDomainOriginLinePaint().setColor(Color.BLACK);
plot.getGraph().getRangeOriginLinePaint().setColor(Color.BLACK);
// Customize domain and range labels.
plot.setDomainLabel("x-vals");
plot.setRangeLabel("y-vals");
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).
setFormat(new DecimalFormat("0"));
// Make the domain and range step correctly
plot.setRangeBoundaries(40, 160, BoundaryMode.FIXED);
plot.setRangeStep(StepMode.INCREMENT_BY_VAL, 20);
plot.setDomainStep(StepMode.INCREMENT_BY_VAL, 60);
plot.setLinesPerDomainLabel(2);
series = getSeries();
LineAndPointFormatter lpFormat = new LineAndPointFormatter(
Color.BLACK,
Color.GRAY,
null, // No fill
new PointLabelFormatter(Color.TRANSPARENT) // Don't show text at points
);
lpFormat.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(3));
lpFormat.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(6));
plot.addSeries(series, lpFormat);
plot.redraw();
}
private SimpleXYSeries getSeries() {
Integer[] xVals = new Integer[SERIES_LEN];
Integer[] yVals = new Integer[SERIES_LEN];
xVals[0] = 0;
yVals[0] = 0;
for (int i = 1; i < SERIES_LEN; i += 1){
xVals[i] = xVals[i-1] + (int)(Math.random() * i);
yVals[i] = (int)(Math.random() * 140);
}
return new SimpleXYSeries(
Arrays.asList(xVals),
Arrays.asList(yVals),
"Sample Series");
}
public void onGraphStyleToggle(View v) {
boolean styleOn = ((ToggleButton) v).isChecked();
RectF rect = plot.getGraph().getGridRect();
BitmapShader myShader = new BitmapShader(
Bitmap.createScaledBitmap(
BitmapFactory.decodeResource(
getResources(),
R.drawable.graph_background),
1,
(int) rect.height(),
false),
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT);
Matrix m = new Matrix();
m.setTranslate(rect.left, rect.top);
myShader.setLocalMatrix(m);
if (styleOn)
plot.getGraph().getGridBackgroundPaint().setShader(
myShader);
else
plot.getGraph().getGridBackgroundPaint().setShader(WHITE_SHADER);
plot.redraw();
}
}
@@ -0,0 +1,328 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.XYSeries;
import com.androidplot.ui.*;
import com.androidplot.xy.*;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.Arrays;
/**
* Demonstration of the usage of Marker and RectRegion.
*/
public class XYRegionExampleActivity extends Activity {
private static final float HOME_RUN_DIST = 325;
private static final int LINE_THICKNESS_DP = 4;
private static final int POINT_SIZE_DP = 7;
private XYPlot plot;
private final Number[] timHits = {105, 252, 216, 10, 301, 320, 220, 350, 12, 250, 353};
private final Number[] nickHits = {110, 191, 61, 300, 205, 40, 224, 371, 289, 101, 10};
private LineAndPointFormatter timFormatter;
private LineAndPointFormatter nickFormatter;
private XYSeries timSeries;
private XYSeries nickSeries;
private RectRegion shortRegion;
private RectRegion warmupRegion;
private RectRegion homeRunRegion;
private XYRegionFormatter shortRegionFormatter;
private XYRegionFormatter warmupRegionFormatter;
private XYRegionFormatter homeRunRegionFormatter;
private CheckBox timCB;
private CheckBox nickCB;
private CheckBox r2CheckBox;
private CheckBox r3CheckBox;
private CheckBox r4CheckBox;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xyregion_example);
plot = findViewById(R.id.xyRegionExamplePlot);
timCB = findViewById(R.id.s1CheckBox);
timCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
onS1CheckBoxClicked();
}
});
nickCB = findViewById(R.id.s2CheckBox);
nickCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
onS2CheckBoxClicked();
}
});
r2CheckBox = findViewById(R.id.r2CheckBox);
r2CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
onCheckBoxClicked(r2CheckBox, timFormatter, shortRegionFormatter, shortRegion);
}
});
r3CheckBox = findViewById(R.id.r3CheckBox);
r3CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
onCheckBoxClicked(r3CheckBox, nickFormatter, warmupRegionFormatter, warmupRegion);
}
});
r4CheckBox = findViewById(R.id.r4CheckBox);
r4CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
onCheckBoxClicked(r4CheckBox, nickFormatter, homeRunRegionFormatter, homeRunRegion);
}
});
seriesSetup();
markerSetup();
axisLabelSetup();
regionSetup();
makePlotPretty();
}
private void onS1CheckBoxClicked() {
if (timCB.isChecked()) {
plot.addSeries(timSeries, timFormatter);
r2CheckBox.setEnabled(true);
} else {
plot.removeSeries(timSeries);
r2CheckBox.setEnabled(false);
}
plot.redraw();
}
private void onS2CheckBoxClicked() {
if (nickCB.isChecked()) {
plot.addSeries(nickSeries, nickFormatter);
r3CheckBox.setEnabled(true);
r4CheckBox.setEnabled(true);
} else {
plot.removeSeries(nickSeries);
r3CheckBox.setEnabled(false);
r4CheckBox.setEnabled(false);
}
plot.redraw();
}
/**
* Processes a run box event
* @param cb The checkbox event origin
* @param lpf LineAndPointFormatter with which rr and rf are to be added/removed
* @param rf The XYRegionFormatter with which rr should be rendered
* @param rr The RectRegion to add/remove
*/
private void onCheckBoxClicked(CheckBox cb, LineAndPointFormatter lpf,
XYRegionFormatter rf, RectRegion rr) {
if (cb.isChecked()) {
lpf.removeRegion(rr);
} else {
lpf.addRegion(rr, rf);
}
}
/**
* Cleans up the plot's general layout and color scheme
*/
private void makePlotPretty() {
// use a 2x5 grid with room for 10 items:
plot.getLegend().setTableModel(new DynamicTableModel(4, 2));
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT)
.setFormat(new NumberFormat() {
@Override
public StringBuffer format(double value, StringBuffer buffer,
FieldPosition field) {
return new StringBuffer(value + "'");
}
@Override
public StringBuffer format(long value, StringBuffer buffer,
FieldPosition field) {
throw new UnsupportedOperationException("Not yet implemented.");
}
@Override
public Number parse(String string, ParsePosition position) {
throw new UnsupportedOperationException("Not yet implemented.");
}
});
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM)
.setFormat(new DecimalFormat("#"));
plot.getGraph().setDomainGridLinePaint(null);
plot.getLegend().setWidth(PixelUtils.dpToPix(100), SizeMode.FILL);
// reposition the grid so that it rests above the bottom-left
// edge of the graph widget:
plot.getLegend().position(
50,
HorizontalPositioning.ABSOLUTE_FROM_CENTER,
200,
VerticalPositioning.ABSOLUTE_FROM_TOP,
Anchor.TOP_MIDDLE);
plot.setRangeBoundaries(0, BoundaryMode.FIXED, 500, BoundaryMode.FIXED);
}
/**
* Create 4 XYSeries from the values defined above add add them to the plot.
* Also add some arbitrary regions.
*/
private void seriesSetup() {
// TIM
timFormatter = new LineAndPointFormatter(Color.YELLOW, Color.YELLOW, null, null);
timFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
timFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
timFormatter.setInterpolationParams(new CatmullRomInterpolator.Params(8,
CatmullRomInterpolator.Type.Centripetal));
timSeries = new SimpleXYSeries(Arrays.asList(timHits),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Tim");
plot.addSeries(timSeries, timFormatter);
// SERIES #2:
nickFormatter = new LineAndPointFormatter(Color.BLUE, Color.BLUE, null, null);
nickFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
nickFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
nickFormatter.setInterpolationParams(new CatmullRomInterpolator.Params(8,
CatmullRomInterpolator.Type.Centripetal));
nickSeries = new SimpleXYSeries(Arrays.asList(nickHits),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Nick");
plot.addSeries(nickSeries, nickFormatter);
plot.setRangeStep(StepMode.INCREMENT_BY_VAL, 100);
plot.setDomainStep(StepMode.INCREMENT_BY_VAL, 1);
}
/**
* Add some color coded regions to our axis labels.
*/
private void axisLabelSetup() {
// DOMAIN
// TODO
// plot.getGraphWidget().addDomainLineLabelFormatter(
// Double.NEGATIVE_INFINITY, 2, new SimpleLineLabelFormatter(Color.GRAY));
// plot.getGraphWidget().addDomainLineLabelFormatter(
// 2, Double.POSITIVE_INFINITY, new SimpleLineLabelFormatter(Color.WHITE));
// // RANGE
// plot.getGraphWidget().addRangeLineLabelFormatter(
// Double.NEGATIVE_INFINITY, HOME_RUN_DIST, new SimpleLineLabelFormatter(Color.RED));
// plot.getGraphWidget().addRangeLineLabelFormatter(
// HOME_RUN_DIST, Double.POSITIVE_INFINITY, new SimpleLineLabelFormatter(Color.GREEN));
}
/**
* Add some markers to our plot.
*/
private void markerSetup() {
YValueMarker fenwayLfMarker = new YValueMarker(
380, // y-val to mark
"Fenway Park LF Wall", // marker label
new HorizontalPosition(
// object instance to set text positioning on the marker
PixelUtils.dpToPix(5), // 5dp offset
HorizontalPositioning.ABSOLUTE_FROM_RIGHT), // offset origin
Color.BLUE, // line paint color
Color.BLUE); // text paint color
YValueMarker attRfMarker = new YValueMarker(
309, // y-val to mark
"ATT Park RF Wall", // marker label
new HorizontalPosition(
// object instance to set text positioning on the marker
PixelUtils.dpToPix(5), // 5dp offset
HorizontalPositioning.ABSOLUTE_FROM_RIGHT), // offset origin
Color.CYAN, // line paint color
Color.CYAN); // text paint color
fenwayLfMarker.getTextPaint().setTextSize(PixelUtils.dpToPix(14));
attRfMarker.getTextPaint().setTextSize(PixelUtils.dpToPix(14));
DashPathEffect dpe = new DashPathEffect(
new float[] {PixelUtils.dpToPix(2), PixelUtils.dpToPix(2)}, 0);
fenwayLfMarker.getLinePaint().setPathEffect(dpe);
attRfMarker.getLinePaint().setPathEffect(dpe);
plot.addMarker(fenwayLfMarker);
plot.addMarker(attRfMarker);
}
/**
* Add some fill regions to our series data
*/
private void regionSetup() {
// and another region:
shortRegionFormatter = new XYRegionFormatter(Color.RED);
shortRegionFormatter.getPaint().setAlpha(60);
shortRegion = new RectRegion(
2, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, HOME_RUN_DIST, "Short");
timFormatter.addRegion(shortRegion, shortRegionFormatter);
nickFormatter.addRegion(shortRegion, shortRegionFormatter);
// the next three regions are horizontal regions with minY/maxY
// set to negative and positive infinity respectively.
warmupRegionFormatter = new XYRegionFormatter(Color.LTGRAY);
warmupRegionFormatter.getPaint().setAlpha(60);
warmupRegion = new RectRegion(
0, 2, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, "Warmup");
timFormatter.addRegion(warmupRegion, warmupRegionFormatter);
nickFormatter.addRegion(warmupRegion, warmupRegionFormatter);
homeRunRegionFormatter = new XYRegionFormatter(Color.GREEN);
homeRunRegionFormatter.getPaint().setAlpha(60);
homeRunRegion = new RectRegion(
2, Double.POSITIVE_INFINITY, HOME_RUN_DIST, Double.POSITIVE_INFINITY, "H. Run");
timFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
nickFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
nickFormatter.setFillDirection(FillDirection.RANGE_ORIGIN);
}
}
@@ -0,0 +1,111 @@
/*
* Copyright 2015 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos.widget;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.widget.RemoteViews;
import com.androidplot.demos.R;
import com.androidplot.ui.*;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYSeries;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYPlot;
import java.util.Arrays;
public class DemoAppWidgetProvider extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int widgetId : appWidgetIds) {
XYPlot plot = new XYPlot(context, "Widget Example");
final int h = (int) context.getResources().getDimension(R.dimen.sample_widget_height);
final int w = (int) context.getResources().getDimension(R.dimen.sample_widget_width);
plot.getGraph().setMargins(0, 0, 0 , 0);
plot.getGraph().setPadding(0, 0, 0, 0);
plot.getGraph().position(0, HorizontalPositioning.ABSOLUTE_FROM_LEFT, 0,
VerticalPositioning.ABSOLUTE_FROM_TOP, Anchor.LEFT_TOP);
plot.getGraph().setSize(Size.FILL);
plot.getLayoutManager().moveToTop(plot.getTitle());
plot.getGraph().setLineLabelEdges(XYGraphWidget.Edge.LEFT, XYGraphWidget.Edge.BOTTOM);
plot.getGraph().getLineLabelInsets().setLeft(PixelUtils.dpToPix(16));
plot.getGraph().getLineLabelInsets().setBottom(PixelUtils.dpToPix(4));
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).getPaint().setColor(Color.RED);
plot.getGraph().getGridInsets().setTop(PixelUtils.dpToPix(12));
plot.getGraph().getGridInsets().setRight(PixelUtils.dpToPix(12));
plot.getGraph().getGridInsets().setLeft(PixelUtils.dpToPix(36));
plot.getGraph().getGridInsets().setBottom(PixelUtils.dpToPix(16));
plot.measure(w, h);
plot.layout(0, 0, w, h);
Number[] series1Numbers = {1, 4, 2, 8, 4, 16, 8, 32, 16, 64};
Number[] series2Numbers = {5, 2, 10, 5, 20, 10, 40, 20, 80, 40};
// Turn the above arrays into XYSeries':
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(series1Numbers), // SimpleXYSeries takes a List so turn our array into a List
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, // Y_VALS_ONLY means use the element index as the x value
"Series1"); // Set the display title of the series
// same as above
XYSeries series2 = new SimpleXYSeries(Arrays.asList(series2Numbers),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");
// Create a formatter to use for drawing a series using LineAndPointRenderer:
LineAndPointFormatter series1Format = new LineAndPointFormatter(
Color.rgb(0, 200, 0), // line color
Color.rgb(0, 100, 0), // point color
null, null); // fill color (none)
// add a new series' to the xyplot:
plot.addSeries(series1, series1Format);
// same as above:
plot.addSeries(series2,
new LineAndPointFormatter(
Color.rgb(0, 0, 200), Color.rgb(0, 0, 100), null, null));
// reduce the number of range labels
plot.setLinesPerRangeLabel(3);
plot.setLinesPerDomainLabel(2);
// hide the legend:
plot.getLegend().setVisible(false);
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.demo_app_widget);
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
plot.draw(new Canvas(bitmap));
rv.setImageViewBitmap(R.id.imgView, bitmap);
appWidgetManager.updateAppWidget(widgetId, rv);
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.androidplot.xy.XYPlot
android:id="@+id/plot"
style="@style/APDefacto.Light"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
ap:gridClippingEnabled="false"
ap:gridInsetLeft="35dp"
ap:gridInsetRight="10dp"
ap:title="Growth" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<Spinner
android:id="@+id/spRenderStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Spinner
android:id="@+id/spSeriesSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<Spinner
android:id="@+id/spWidthStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RelativeLayout
android:id="@+id/sectionGraph"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<SeekBar
android:id="@+id/sbFixed"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="300"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:progress="10" />
<SeekBar
android:id="@+id/sbVariable"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="50"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:progress="1" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<CheckBox
android:id="@+id/s1CheckBox"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="Series 1" />
<CheckBox
android:id="@+id/s2CheckBox"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="Series 2" />
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Dark"
android:id="@+id/plot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:title="A Bubble Chart"
ap:rangeTitle="range"
ap:domainTitle="domain"
ap:lineLabels="left|bottom"
ap:lineLabelRotationBottom="-45"/>
</LinearLayout>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2016 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="@color/ap_black">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Light"
android:id="@+id/plot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:previewMode="candlestick"
ap:title="Daily Price"
ap:domainTitle="Day"
ap:rangeTitle="Price"
ap:gridClippingEnabled="false"
ap:legendVisible="false"
ap:lineLabelTextSizeLeft="12sp"
ap:lineLabelTextSizeBottom="15sp"
ap:lineLabelInsetLeft="32dp"
ap:gridInsetLeft="35dp"/>
</LinearLayout>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/imgView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerInside"></ImageView>
</LinearLayout>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Dark"
android:id="@+id/plot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:title="Min Wage vs Cost by Year"
ap:lineLabels="left|bottom|right"
ap:gridInsetLeft="50dp"
ap:lineLabelInsetLeft="45dp"
ap:gridInsetRight="40dp"
ap:lineLabelInsetRight="35dp"
ap:lineLabelRotationBottom="-45"/>
</LinearLayout>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.androidplot.xy.XYPlot
android:id="@+id/dynamicXYPlot"
style="@style/APDefacto.Dark"
androidplot.renderMode="use_background_thread"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:domainTitle="Domain"
ap:legendAnchor="right_bottom"
ap:legendHeight="25dp"
ap:legendIconHeight="15dp"
ap:legendIconWidth="15dp"
ap:legendTextSize="15sp"
ap:rangeTitle="Range"
ap:title="A Dynamic XY Plot" />
</LinearLayout>
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2016 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Dark"
android:id="@+id/plot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:renderMode="use_background_thread"
ap:title="ECG Example"
ap:rangeTitle="range"
ap:domainTitle="domain"/>
</LinearLayout>
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2016 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Dark"
android:id="@+id/plot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:title="A Simple XY Plot"
ap:rangeTitle="range"
ap:domainTitle="domain"
ap:lineLabels="left|bottom|top|right"
ap:gridInsetRight="30dp"
ap:gridInsetTop="30dp"
ap:gridInsetBottom="20dp"
ap:lineLabelInsetRight="25dp"
ap:lineLabelInsetTop="25dp"
ap:lineLabelRotationBottom="-45"
ap:lineLabelRotationTop="0"
ap:lineLabelAlignTop="center"
ap:domainOriginLineThickness="4dp"
ap:rangeOriginLineThickness="4dp"/>
</LinearLayout>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000"
xmlns:android="http://schemas.android.com/apk/res/android">
<ListView android:id="@+id/listView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Light"
android:id="@+id/xyplot"
android:layout_width="fill_parent"
android:layout_height="250dp"
ap:title="an xy plot"/>
</LinearLayout>
@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/startSimplePieExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Pie Chart"/>
<Button
android:id="@+id/startSimpleXYExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="A Simple XY Plot"/>
<Button
android:id="@+id/animatedXYPlotExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Animated XY Plot"/>
<Button
android:id="@+id/startScatterExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="XY Scatter Plot"/>
<Button
android:id="@+id/startDynamicXYExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="A Dynamic XY Plot"/>
<Button
android:id="@+id/startCandlestickExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Candlestick Chart"/>
<Button
android:id="@+id/startOrSensorExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Realtime Orientation Sensor Plot"/>
<Button
android:id="@+id/startDualScaleExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Dual Scale XY"/>
<Button
android:id="@+id/startTimeSeriesExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/ts_title"/>
<Button
android:id="@+id/startStepChartExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Step Chart"
/>
<Button
android:id="@+id/startScrollZoomButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Scroll and Zoom"
/>
<Button
android:id="@+id/startBarPlotExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bar Plot"/>
<Button
android:id="@+id/startXyRegionExampleButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="XYRegion Example"
android:enabled="true"/>
<Button
android:id="@+id/startXyListViewExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ListView of XYPlots"
android:enabled="true"/>
<Button
android:id="@+id/startXyRecyclerViewExButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="RecyclerView of XYPlots"
android:enabled="true"/>
<Button
android:id="@+id/startXYPlotWithBgImgExample"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="XY Background Example"
android:enabled="true"/>
<Button
android:id="@+id/startECGExample"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ECG Example"
android:enabled="true"/>
<Button
android:id="@+id/fxPlotExample"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="f(x) Example"
android:enabled="true"/>
<Button
android:id="@+id/bubbleChartExample"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bubble Chart Example"
android:enabled="true"/>
</LinearLayout>
</ScrollView>
<TextView
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:gravity="center"
android:text="http://androidplot.com"/>
</LinearLayout>
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="horizontal"
android:gravity="center"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Dark"
android:id="@+id/aprLevelsPlot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="0dp"
android:layout_weight="3"
android:layout_marginTop="10px"
android:layout_marginLeft="10px"
android:layout_marginRight="10px"
ap:renderMode="use_background_thread"
ap:title="Levels"/>
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Dark"
android:id="@+id/aprHistoryPlot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="0dp"
android:layout_weight="1"
android:layout_marginTop="10px"
android:layout_marginLeft="10px"
android:layout_marginRight="10px"
androidPlot.backgroundPaint.color="#000000"
androidPlot.borderPaint.color="#000000"
androidplot.renderMode="use_background_thread"
ap:title="History"
ap:domainTitle="Domain"
ap:rangeTitle="Range"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/hwAccelerationCb"
android:visibility="gone"
android:text="HW Acceleration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:id="@+id/showFpsCb"
android:text="Show FPS"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.androidplot.pie.PieChart
android:id="@+id/mySimplePieChart"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
androidPlot.title.text="A Simple Pie Chart"
androidPlot.title.labelPaint.textSize="@dimen/title_font_size"/>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:text="Donut Size"
android:id="@+id/donutSizeSeekLabel"/>
<SeekBar
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:max="90"
android:progress="50"
android:id="@+id/donutSizeSeekBar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:text="unknown"
android:id="@+id/donutSizeTextView"/>
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:background="@color/ap_white"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp" />
</LinearLayout>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<com.androidplot.xy.XYPlot xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:id="@+id/plot"
style="@style/APDefacto.Light"
android:layout_width="fill_parent"
android:layout_height="250dp"
ap:title="an xy plot" />
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Dark"
android:id="@+id/plot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:title="A Scatter Plot"
ap:rangeTitle="range"
ap:domainTitle="domain"/>
</LinearLayout>
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Dark"
android:id="@+id/plot"
android:layout_width="match_parent"
android:layout_height="match_parent"
ap:title="A Simple XY Plot"
ap:rangeTitle="range"
ap:domainTitle="domain"
ap:lineLabels="left|bottom"
ap:lineLabelRotationBottom="-45"
android:layout_weight="1"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="15dp">
</TextView>
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.androidplot.xy.XYPlot
android:id="@+id/stepChartExamplePlot"
style="@style/APDefacto.Dark"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:domainTitle="time (secs)"
ap:rangeTitle="server state"
ap:title="HTTP Server State (15 Sec)" />
</LinearLayout>
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.androidplot.xy.XYPlot
android:id="@+id/plot1"
style="@style/APDefacto.Light"
renderMode="use_main_thread"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:backgroundColor="@color/ap_white"
ap:graphBackgroundColor="@color/ap_white"
ap:gridInsetBottom="40dp"
ap:gridInsetLeft="35dp"
ap:lineLabelInsetBottom="25dp"
ap:lineLabelInsetLeft="25dp"
ap:lineLabelRotationBottom="-45"
ap:paddingBottom="10dp"
ap:paddingLeft="10dp"
ap:paddingRight="10dp"
ap:paddingTop="10dp"
ap:title="@string/ts_plot1_title" />
</LinearLayout>
@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/ap_black"
android:orientation="vertical">
<com.androidplot.xy.XYPlot
android:id="@+id/plot"
style="@style/APDefacto.Dark"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
ap:drawGridOnTop="true"
ap:renderMode="use_background_thread"
ap:title="A Simple XY Plot" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="5"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:text="Pan"
android:textSize="12sp" />
<Spinner
android:id="@+id/pan_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="0dp">
</Spinner>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="3"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:text="Zoom"
android:textSize="12sp" />
<Spinner
android:id="@+id/zoom_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="0dp">
</Spinner>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/resetButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Reset" />
</LinearLayout>
@@ -0,0 +1,47 @@
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Light"
android:id="@+id/graph_metrics"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
ap:gridClippingEnabled="true"/>
<ToggleButton
android:id="@+id/style_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/graph_metrics"
android:layout_alignRight="@id/graph_metrics"
android:layout_marginTop="15dp"
android:layout_marginRight="15dp"
android:textOn="bg on"
android:textOff="bg off"
android:onClick="onGraphStyleToggle" />
</RelativeLayout>
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Dark"
android:id="@+id/xyRegionExamplePlot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:graphMarginTop="10dp"
ap:graphMarginLeft="25dp"
ap:graphMarginRight="0dp"
ap:graphMarginBottom="20dp"
ap:title="Batting Practice Stats"
ap:domainTitle="Pitch #"
ap:rangeTitle="Distance"
android:layout_weight="1"
/>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<CheckBox
android:id="@+id/s1CheckBox"
android:text="Tim"
android:checked="true"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<CheckBox
android:id="@+id/s2CheckBox"
android:text="Nick"
android:checked="true"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<CheckBox
android:id="@+id/r1CheckBox"
android:text="R1"
android:checked="true"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<CheckBox
android:id="@+id/r2CheckBox"
android:text="R2"
android:checked="true"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<CheckBox
android:id="@+id/r3CheckBox"
android:text="R3"
android:checked="true"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<CheckBox
android:id="@+id/r4CheckBox"
android:text="R4"
android:checked="true"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<CheckBox
android:id="@+id/r5CheckBox"
android:text="R5"
android:checked="true"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,4 @@
<resources>
<dimen name="title_font_size">30dp</dimen>
<dimen name="pie_segment_label_font_size">20dp</dimen>
</resources>
@@ -0,0 +1,17 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="pie_segment_label_font_size">10sp</dimen>
<dimen name="title_font_size">20sp</dimen>
<dimen name="domain_label_font_size">13sp</dimen>
<dimen name="range_label_font_size">13sp</dimen>
<dimen name="range_tick_label_font_size">15sp</dimen>
<dimen name="domain_tick_label_font_size">15sp</dimen>
<dimen name="legend_text_font_size">20sp</dimen>
<dimen name="sample_widget_height">72dp</dimen>
<dimen name="sample_widget_width">294dp</dimen>
</resources>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<resources>
<string name="app_name">Androidplot Demos</string>
<string name="sxy_title">A Simple XY Plot</string>
<string name="ts_title">Time Series</string>
<string name="ts_plot1_title">UFO Sightings</string>
</resources>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
strokePaint.color="#FFCC66"
fillPaint.color="#FF0000"/>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
strokePaint.color="#2255AA"
fillPaint.color="#AABBFF"/>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
strokePaint.color="#A18459"
fillPaint.color="#604219"/>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
wickPaint.color="#000000"
upperCapPaint.color="#000000"
lowerCapPaint.color="#000000"
risingBodyStrokePaint.color="#000000"
fallingBodyStrokePaint.color="#000000"/>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="@dimen/sample_widget_width"
android:minHeight="@dimen/sample_widget_height"
android:updatePeriodMillis="86400000"
android:initialLayout="@layout/demo_app_widget"
android:resizeMode="horizontal|vertical">
</appwidget-provider>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2016 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
linePaint.strokeWidth="5dp"
linePaint.color="#00AA00"
vertexPaint.color="#00000000"
fillPaint.color="#00000000"/>
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
linePaint.strokeWidth="5dp"
linePaint.color="#00AA00"
vertexPaint.color="#007700"
vertexPaint.strokeWidth="20dp"
fillPaint.color="#00000000"
pointLabelFormatter.textPaint.color="#CCCCCC"/>
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
linePaint.strokeWidth="5dp"
linePaint.color="#0000AA"
vertexPaint.strokeWidth="20dp"
vertexPaint.color="#000099"
fillPaint.color="#00000000"
pointLabelFormatter.textPaint.color="#CCCCCC"/>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
fillPaint.color="#FF0000"
labelPaint.textSize="@dimen/pie_segment_label_font_size"/>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
fillPaint.color="#00FF00"
labelPaint.textSize="@dimen/pie_segment_label_font_size"/>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
fillPaint.color="#0000FF"
labelPaint.textSize="@dimen/pie_segment_label_font_size"/>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
fillPaint.color="#FF00FF"
labelPaint.textSize="@dimen/pie_segment_label_font_size"/>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
linePaint.color="#00000000"
vertexPaint.color="#6666FF"
vertexPaint.strokeWidth="10dp"
fillPaint.color="#00000000"/>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 AndroidPlot.com
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<config
linePaint.color="#00000000"
vertexPaint.strokeWidth="10dp"
vertexPaint.color="#FFCC66"
fillPaint.color="#00000000"/>