Related
I'm trying to create a mountain chart using SciChart, but I need to create using Logarithmic, I tried the below code, but dont change chart and missing YAxis label.
I change the demo SciChart to it:
public class MountainChartFragment extends ExampleBaseFragment {
#BindView(R.id.chart)
SciChartSurface surface;
private double selectedLogBase = 10d;
#Override
protected int getLayoutId() {
return R.layout.example_single_chart_fragment;
}
#Override
protected void initExample() {
//final IAxis xBottomAxis = sciChartBuilder.newDateAxis().withGrowBy(0.1d, 0.1d).build();
final IAxis xBottomAxis = sciChartBuilder.newDateAxis().withGrowBy(0.1d, 0.1d).build();
final IAxis yRightAxis = sciChartBuilder.newLogarithmicNumericAxis().withScientificNotation(ScientificNotation.LogarithmicBase).withLogarithmicBase(selectedLogBase).withGrowBy(0.1d, 0.1d).build();
//final IAxis yRightAxis = sciChartBuilder.newNumericAxis().withGrowBy(0.1d, 0.1d).build();
final PriceSeries priceData = DataManager.getInstance().getPriceDataIndu(getActivity());
final IXyDataSeries<Date, Double> dataSeries = sciChartBuilder.newXyDataSeries(Date.class, Double.class).build();
dataSeries.append(priceData.getDateData(), priceData.getCloseData());
final FastMountainRenderableSeries rSeries = sciChartBuilder.newMountainSeries()
.withZeroLine(0.001)
.withDataSeries(dataSeries)
.withStrokeStyle(0xAAFFC9A8, 1f, true)
.withAreaFillLinearGradientColors(0xAAFF8D42, 0x88090E11)
.build();
UpdateSuspender.using(surface, new Runnable() {
#Override
public void run() {
Collections.addAll(surface.getXAxes(), xBottomAxis);
Collections.addAll(surface.getYAxes(), yRightAxis);
Collections.addAll(surface.getRenderableSeries(), rSeries);
Collections.addAll(surface.getChartModifiers(), sciChartBuilder.newModifierGroupWithDefaultModifiers().build());
sciChartBuilder.newAnimator(rSeries).withWaveTransformation().withInterpolator(new DecelerateInterpolator()).withDuration(3000).withStartDelay(350).start();
}
});
}
}
But dont worked
There are no labels because default TickProvider implementation for LogarithmicNumericAxis can't generate any ticks for auto calculated VisibleRange which is set for YAxis ( it has next values - Min = 10460.814629837885, Max = 13048.710993563885) The nearest values which which would satisfy LogBase = 10 would be 10000 and then 100000 and data set of example lies between these two values so TickProvider returns zero values to render.
In this case there are two possible workarounds:
Try to pick up some other LogBase value;
Set some alternative TickProvider implementation for YAxis (e.g. you can try to use TickProvider for NumericAxis or create your own implementation):
yRightAxis.setTickProvider(new NumericTickProvider());
I change the code and worked well. This is my code:
xAxis = sciChartBuilder.newNumericAxis().withGrowBy(0.1d, 0.1d).withVisibleRange(1.1, 2.7).build();
yAxis = generateLogarithmicAxis();
//yAxis = sciChartBuilder.newNumericAxis().withGrowBy(0.1d, 0.1d).build();
//yAxis.setTickProvider(new NumericTickProvider());
final SimpleDateFormat formatDate = new SimpleDateFormat("yyyyMMdd");
String data1 = "20190401";
Date date1 = null;
Calendar c = Calendar.getInstance();
final IXyDataSeries<Date, Double> dataSeries = sciChartBuilder.newXyDataSeries(Date.class, Double.class).build();
try {
date1 = formatDate.parse(data1);
for(int i = 0 ; i<1000 ; i+=10){
double random = Math.random() * 100.0 + 5;
dataSeries.append(date1, random);
c.setTime(date1);
c.add(Calendar.DATE, 1);
date1 = c.getTime();
}
} catch (ParseException e) {
e.printStackTrace();
}
final FastLineRenderableSeries rSeries = sciChartBuilder.newLineSeries().withZeroLine(0.01d).withDataSeries(dataSeries).withStrokeStyle(0xFF279B27, 1f, true).build();
UpdateSuspender.using(surface, new Runnable() {
#Override
public void run() {
Collections.addAll(surface.getXAxes(), xAxis);
Collections.addAll(surface.getYAxes(), yAxis);
Collections.addAll(surface.getRenderableSeries(), rSeries);
Collections.addAll(surface.getChartModifiers(), sciChartBuilder.newModifierGroupWithDefaultModifiers().build());
sciChartBuilder.newAnimator(rSeries).withSweepTransformation().withInterpolator(new DecelerateInterpolator()).withDuration(3000).withStartDelay(350).start();
}
});
I am working on an Android app and I have a graph of sensor readings: temp/humidity/wind plotted on Y axis, and then time/date on the X-axis. I am using the SimpleGraph library. For the most part everything works great. However, there are a 2-3 issues I've gotten stuck on.
If I specify a number for labels, such as 3 for my main screen, It won't scroll to the end, or which would be preferably, it doesn't just show 3 labels and all the data for the time specified. Instead it shows me the first three labels and cuts the data. If I try graph.getViewport().scrollToEnd(); nothing changes.
On my 'FullGraphActivity' I am still missing the last couple of hours of data...sometimes. Othertimes, it will show.
So I know I am getting the correct data points because my logs show them. I am pretty sure they are being plotted out of view. What I'd really like is to figure out how to get the data and labels to correctly plot based on my time selection. Such as day / week / month. I've included the two main classes, and an example call for the 3 labeled call.
I'm probably missing something simple. Appreciate any suggestions, comments.
Thanks!
Call from main screen with label count specified:
graphTemp = (GraphView) findViewById(R.id.graphTemp);
try {
GraphUtility gu = new GraphUtility(1,1,3,true,false, this,celsius);
gu.grapher( this,graphTemp, gu.seriesBuilder(
gu.getTempData(gu.getSixHours())));
This is where I am setting up the simple graph:
public class GraphUtility {
public int focus;
public Activity activity;
public MainActivity mainActivity;
public Context context;
Constants constants;
private final static int graphColor
Color.parseColor("#6a0c05");
private double maxYBound = 0;
private double minYBound = 999;
private int time = 0;
private int labelCount = 0;
private boolean maxy = true;
private boolean miny = true;
private boolean celsius;
public GraphUtility(int focus, int time, int labelCount,boolean maxy, boolean miny, MainActivity mainActivity, boolean celsius) {
this.focus = focus;
this.time = time;
this.labelCount = labelCount;
context = mainActivity;
this.mainActivity = mainActivity;
this.miny = miny;
this.maxy = maxy;
this.celsius = celsius;
}
public void grapher(Context context, GraphView graph, LineGraphSeries[] seriesArray){
try{
graph.removeAllSeries();
LineGraphSeries series = new LineGraphSeries();
series.clearReference(graph);
if(focus==0){
for(int i = 0; i<seriesArray.length; i++){
// series = new LineGraphSeries();
series = seriesArray[i];
series.setDrawBackground(true);
if(i == 0) {
series.setColor(Color.parseColor("#8d1007"));
series.setBackgroundColor(Color.parseColor("#8d1007"));
}
if(i == 1) {
series.setColor(Color.parseColor("#551a8b"));
series.setBackgroundColor(Color.parseColor("#551a8b"));
}
if(i == 2) {
series.setColor(Color.parseColor("#FF0008F0"));
series.setBackgroundColor(Color.parseColor("#FF0008F0"));
}
series.setDataPointsRadius(2);
series.setThickness(2);
graph.addSeries(series);
}
}
if(focus == 1){
series = seriesArray[0];
series.setDrawBackground(true);
series.setColor(Color.parseColor("#8d1007"));
series.setBackgroundColor(Color.parseColor("#8d1007"));
}
if(focus == 2){
series = seriesArray[1];
series.setDrawBackground(true);
series.setColor(Color.parseColor("#8d1007"));
series.setBackgroundColor(Color.parseColor("#8d1007"));
}
if(focus == 3){
series = seriesArray[2];
series.setDrawBackground(true);
series.setColor(Color.parseColor("#8d1007"));
series.setBackgroundColor(Color.parseColor("#8d1007"));
}
series.setDataPointsRadius(2);
series.setThickness(2);
graph.addSeries(series);
//graph.addSeries(series);
graph.getGridLabelRenderer().setGridColor(graphColor);
graph.getGridLabelRenderer().setHorizontalLabelsColor(graphColor);
graph.getGridLabelRenderer().setVerticalLabelsColor(graphColor);
graph.getGridLabelRenderer().setGridStyle(GridLabelRenderer.GridStyle.BOTH);
graph.getViewport().scrollToEnd();
//Add 5 percent for easier readability
if(maxy) {
graph.getViewport().setYAxisBoundsManual(true);
maxYBound = maxYBound + (maxYBound* .05);
maxYBound= 5*(Math.ceil(Math.abs(maxYBound/5)));
if(maxYBound ==0){
maxYBound=1;
}
graph.getViewport().setMaxY(maxYBound);
}
//Minus 5 percent
if(minYBound !=0) {
if(miny) {
graph.getViewport().setYAxisBoundsManual(true);
minYBound = minYBound - (minYBound * .05);
minYBound= 5*(Math.floor(Math.abs(minYBound/5)));
Log.d("BTWeather-minYval", String.valueOf(minYBound));
//TODO Empty sensors causes crash.
graph.getViewport().setMinY(minYBound);
}
}
if(labelCount > 0){
graph.getGridLabelRenderer().setNumHorizontalLabels(labelCount);
}
graph.getGridLabelRenderer().setHumanRounding(true);
// graph.getGridLabelRenderer().setTextSize(35);
graph.getGridLabelRenderer().reloadStyles();
java.text.DateFormat dateTimeFormatter = DateFormat.getTimeFormat(context);
if(time==1) {
graph.getGridLabelRenderer().setLabelFormatter(
new DateAsXAxisLabelFormatter(graph.getContext(),
dateTimeFormatter));
}else{
graph.getGridLabelRenderer().setLabelFormatter(
new DateAsXAxisLabelFormatter(graph.getContext()));
}
//
}catch(Exception e){
Log.d("BTWeather-error21", e.toString());
}
}
// TODO Graphs not advancing again showing hours behind instead of latest sensor
public LineGraphSeries[] seriesBuilder(List<Sensors> sensorsList){
LineGraphSeries[] seriesArray = new LineGraphSeries[3];
try{
DataPoint d = null;
DataPoint[] dataPoints = new DataPoint[sensorsList.size()];
DataPoint[] dataPointsH = new DataPoint[sensorsList.size()];
DataPoint[] dataPointsW = new DataPoint[sensorsList.size()];
Date date1 = new Date();
int i = 0;
Log.d("BTWeather-seriesbuilder",
" Length of sensorlist: " + String.valueOf(sensorsList.size()));
if(sensorsList.size()==0){
minYBound = 0;
}
try{
for(Sensors sensor: sensorsList){
findMaxY(sensor);
findMinY(sensor);
try {
date1 = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss").parse(sensor.getmDate());
//Log.d("BTWeather-sensorlistFG",
// String.valueOf(date1)+" - " + String.valueOf(sensor.getmTemp()) );
} catch (ParseException e) {
e.printStackTrace();
}
if( isCelsius()){
d = new DataPoint(date1, Double.valueOf(sensor.getmTemp()));
}else{
double tmp = mainActivity.cToF(Double.valueOf(sensor.getmTemp()));
// Log.d("BTWeather-seriesdump",String.valueOf(tmp));
d = new DataPoint(date1, tmp);
}
dataPoints[i]= d;
d = new DataPoint(date1, Double.valueOf(sensor.getmHumidity()));
dataPointsH[i]=d;
d = new DataPoint(date1, Double.valueOf(sensor.getmWind()));
dataPointsW[i]=d;
i++;
}
seriesArray[0] = new LineGraphSeries<>(dataPoints);
seriesArray[1] = new LineGraphSeries<>(dataPointsH);
seriesArray[2] = new LineGraphSeries<>(dataPointsW);
}catch(Exception e){
Log.d("BTWeather-error20", e.toString());
}
}catch (Exception e){
Log.d("BTWeather-error22", e.toString());
}
return seriesArray;
}
//TODO min / max not resetting propperly for days/weeks etc
public void findMaxY (Sensors sensor){
try{
//Focus passed from main activity on graph click
if(focus ==1){
if( isCelsius()) {
if (Double.valueOf(sensor.getmTemp()) > maxYBound) {
maxYBound = Double.valueOf(sensor.getmTemp());
}
}else if(mainActivity.cToF(Double.valueOf(sensor.getmTemp()))>maxYBound){
maxYBound=mainActivity.cToF(Double.valueOf(sensor.getmTemp()));
}
}
else if(focus == 2){
if( Double.valueOf(sensor.getmHumidity())> maxYBound){
maxYBound = Double.valueOf(sensor.getmHumidity());
}
}
else if(focus == 3){
if(Double.valueOf(sensor.getmWind())> maxYBound){
maxYBound = Double.valueOf(sensor.getmWind());
}
}}
catch (Exception e){
Log.d("BTWeather-error19", e.toString());
}
}
public void findMinY (Sensors sensor){
if(sensor != null) {
try {
//Focus passed from main activity on graph click
if (focus == 1) {
if (isCelsius()) {
if (Double.valueOf(sensor.getmTemp()) < minYBound) {
minYBound = Double.valueOf(sensor.getmTemp());
}
} else if (mainActivity.cToF(Double.valueOf(sensor.getmTemp())) < minYBound) {
minYBound = mainActivity.cToF(Double.valueOf(sensor.getmTemp()));
}
} else if (focus == 2) {
if (Double.valueOf(sensor.getmHumidity()) < minYBound) {
minYBound = Double.valueOf(sensor.getmHumidity());
}
} else if (focus == 3) {
if (Double.valueOf(sensor.getmWind()) < minYBound) {
minYBound = Double.valueOf(sensor.getmWind());
}
}
} catch (Exception e) {
Log.d("BTWeather-error18", e.toString());
}
}else{
minYBound=0;
}
}
//Database
public static String getYesterday(){
//return new Date(System.currentTimeMillis()-24*60*60*1000);
long day = TimeUnit.DAYS.toMillis(1);
String start= DateFormat.format("MM-dd-yyyy HH:mm:ss",
new Date(System.currentTimeMillis() - day)).toString();
return start;
}
public static String getSixHours(){
//return new Date(System.currentTimeMillis()-24*60*60*1000);
long day = TimeUnit.HOURS.toMillis(6);
String start= DateFormat.format("MM-dd-yyyy HH:mm:ss",
new Date(System.currentTimeMillis() - day)).toString();
return start;
}
public static String getWeek(){
//return new Date(System.currentTimeMillis()-24*60*60*1000);
long week = TimeUnit.DAYS.toMillis(7);
String start= DateFormat.format("MM-dd-yyyy HH:mm:ss",
new Date(System.currentTimeMillis() - week)).toString();
return start;
}
public static String getMonth(){
//return new Date(System.currentTimeMillis()-24*60*60*1000);
long month = TimeUnit.DAYS.toMillis(30);
String start= DateFormat.format("MM-dd-yyyy HH:mm:ss",
new Date(System.currentTimeMillis() - month)).toString();
return start;
}
public static Date getMeTomorrow(){
return new Date(System.currentTimeMillis());
}
public List<Sensors> getTempData(String start){
SensorsDatabase sDb = SensorsDatabase.getSensorsDatabase(context);
List<Sensors> dataPoints = null;
Date date1 = new Date();
try {
dataPoints = sDb.sensorsDao().findTempByDate(
start,
DateFormat.format("MM-dd-yyyy HH:mm:ss", getMeTomorrow()).toString());
} catch (Exception e) {
Log.d("BTWeather-error8", String.valueOf(e));
}
return dataPoints;
}
public boolean isCelsius() {
return celsius;
}
}
This activity is for full view of the graph. Here it's mostly working. However, as said above, sometimes the last couple of hours worth of data is being cut off. Say its 2:30, I'll see data & labels up to 12:30
public class FullGraphActivity extends AppCompatActivity {
GraphView graph;
private TextView mTextMessage;
private final static int graphColor = Color.parseColor("#6a0c05");
private MainActivity mainActivity;
private int focus =0;
private int time = 0;
GraphUtility gu;
private boolean celsius;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.graph_hour:
time=1;
if(focus ==1 )
mTextMessage.setText(R.string.graph_hour_temp);
if(focus ==2 )
mTextMessage.setText(R.string.graph_hour_humid);
if(focus ==3 )
mTextMessage.setText(R.string.graph_hour_wind);
try{
gu = new GraphUtility(focus,time,0,true,true,mainActivity,celsius);
gu.grapher(getApplicationContext(),graph,gu.seriesBuilder(gu.getTempData(gu.getYesterday())));
}catch(Exception e){
Log.d("BTWeather-error15", e.toString());
}
return true;
case R.id.graph_day:
time=2;
if(focus ==1 )
mTextMessage.setText(R.string.graph_day_temp);
if(focus ==2 )
mTextMessage.setText(R.string.graph_day_humid);
if(focus ==3 )
mTextMessage.setText(R.string.graph_day_wind);
try{
gu = new GraphUtility(focus,time,0,true,true,mainActivity,celsius );
gu.grapher(getApplicationContext(),graph,gu.seriesBuilder(gu.getTempData(gu.getWeek())));
}catch(Exception e){
Log.d("BTWeather-error15", e.toString());
}
return true;
case R.id.graph_week:
time=3;
if(focus ==1 )
mTextMessage.setText(R.string.graph_week_temp);
if(focus ==2 )
mTextMessage.setText(R.string.graph_week_humid);
if(focus ==3 )
mTextMessage.setText(R.string.graph_week_wind);
try{
gu = new GraphUtility(focus,time,0,true,true,mainActivity,celsius );
gu.grapher(getApplicationContext(),graph,gu.seriesBuilder(gu.getTempData(gu.getMonth())));
}catch(Exception e){
Log.d("BTWeather-error15", e.toString());
}
return true;
}
return false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_full_graph);
Intent mIntent = getIntent();
focus = mIntent.getIntExtra("focus", 0);
celsius = mIntent.getBooleanExtra("celsius", false);
mTextMessage = (TextView) findViewById(R.id.message);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.graphMenu);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
mainActivity = new MainActivity() ;
graph = (GraphView) findViewById(R.id.fullGraph);
// Setting the very 1st item as home screen.
navigation.setSelectedItemId(R.id.graph_hour);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home){
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}
Hopefully this isn't too much info. Again, any comments greatly appreciated. Full code repo if it helps.
Ok, so as usual, after deciding to post I was able to work out a solution with the help of the examples on simplegraphs doc. I thought I mirrored the date example from the doc but I had left out a key section:
// set manual x bounds to have nice steps
graph.getViewport().setMinX(start);
graph.getViewport().setMaxX(System.currentTimeMillis());
graph.getViewport().setXAxisBoundsManual(true);
For some reason I wasn't able to clear each graphs style/data correctly despite using the clear/resets provided in the API. Rather than waste too much time on it I decided to create three graphviews in my layout then hide the ones not in use. This isn't the best method, but it seems to not impact performance. See below for the code changes. Note some changes are made for style reasons.
I changed my grapher method to include the double start which is the time to start from:
Class GraphUtility
public void grapher(Context context, GraphView graph, LineGraphSeries[] seriesArray, Double start){
try{
graph.removeAllSeries();
graph.getGridLabelRenderer().resetStyles();
LineGraphSeries series = new LineGraphSeries();
series.clearReference(graph);
if(focus==0) {
for (int i = 0; i < seriesArray.length; i++) {
// series = new LineGraphSeries();
series = seriesArray[i];
series.setDrawBackground(true);
if (i == 0) {
series.setColor(Color.parseColor("#8d1007"));
series.setBackgroundColor(Color.parseColor("#4D6a0c05"));
}
if (i == 1) {
series.setColor(Color.parseColor("#00004C"));
series.setBackgroundColor(Color.parseColor("#4D00004C"));
}
if (i == 2) {
series.setColor(Color.parseColor("#006600"));
series.setBackgroundColor(Color.parseColor("#4D006600"));
}
series.setDataPointsRadius(4);
series.setThickness(4);
graph.getGridLabelRenderer().setGridColor(graphColor);
graph.getGridLabelRenderer().setHorizontalLabelsColor(graphColor);
graph.getGridLabelRenderer().setVerticalLabelsColor(graphColor);
graph.addSeries(series);
}
}
if(focus == 1){
series = seriesArray[0];
series.setDrawBackground(true);
series.setColor(Color.parseColor("#8d1007"));
series.setBackgroundColor(Color.parseColor("#4D6a0c05"));
graph.getGridLabelRenderer().setGridColor(Color.parseColor("#8d1007"));
graph.getGridLabelRenderer().setHorizontalLabelsColor(Color.parseColor("#8d1007"));
graph.getGridLabelRenderer().setVerticalLabelsColor(Color.parseColor("#8d1007"));
series.setDataPointsRadius(2);
series.setThickness(2);
graph.addSeries(series);
}
if(focus == 2){
series = seriesArray[1];
series.setDrawBackground(true);
series.setColor(Color.parseColor("#00004C"));
series.setBackgroundColor(Color.parseColor("#4D00004C"));
graph.getGridLabelRenderer().setGridColor(Color.parseColor("#00004C"));
graph.getGridLabelRenderer().setHorizontalLabelsColor(Color.parseColor("#00004C"));
graph.getGridLabelRenderer().setVerticalLabelsColor(Color.parseColor("#00004C"));
series.setDataPointsRadius(2);
series.setThickness(2);
graph.addSeries(series);
}
if(focus == 3){
series = seriesArray[2];
series.setDrawBackground(true);
series.setColor(Color.parseColor("#006600"));
series.setBackgroundColor(Color.parseColor("#4D006600"));
graph.getGridLabelRenderer().setGridColor(Color.parseColor("#006600"));
graph.getGridLabelRenderer().setHorizontalLabelsColor(Color.parseColor("#006600"));
graph.getGridLabelRenderer().setVerticalLabelsColor(Color.parseColor("#006600"));
series.setDataPointsRadius(2);
series.setThickness(2);
graph.addSeries(series);
}
graph.getGridLabelRenderer().setGridStyle(GridLabelRenderer.GridStyle.BOTH);
//Add 5 percent for easier readability
Log.d(Constants.LOG_TAG,"MaxY" + String.valueOf(maxYBound));
if(maxy) {
graph.getViewport().setYAxisBoundsManual(true);
maxYBound = maxYBound + (maxYBound* .05);
maxYBound= 5*(Math.ceil(Math.abs(maxYBound/5)));
if(maxYBound ==0){
maxYBound=1;
}
graph.getViewport().setMaxY(maxYBound);
}
//Minus 5 percent
Log.d(Constants.LOG_TAG,"MinY" + String.valueOf(minYBound));
if(minYBound !=0) {
if(miny) {
graph.getViewport().setYAxisBoundsManual(true);
minYBound = minYBound - (minYBound * .05);
minYBound= 5*(Math.floor(Math.abs(minYBound/5)));
Log.d("BTWeather-minYval", String.valueOf(minYBound));
graph.getViewport().setMinY(minYBound);
}
}else{
graph.getViewport().setMinY(minYBound);
}
if(labelCount > 0){
graph.getGridLabelRenderer().setNumHorizontalLabels(labelCount);
}
if(time==1) {
java.text.DateFormat dateTimeFormatter = DateFormat.getTimeFormat(context);
graph.getGridLabelRenderer().setLabelFormatter(
new DateAsXAxisLabelFormatter(graph.getContext(),
dateTimeFormatter));
}else{
graph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(context));
}
//graph.getGridLabelRenderer().setNumHorizontalLabels(labelCount); // only 4 because of the space
// set manual x bounds to have nice steps
graph.getViewport().setMinX(start);
graph.getViewport().setMaxX(System.currentTimeMillis());
graph.getViewport().setXAxisBoundsManual(true);
// as we use dates as labels, the human rounding to nice readable numbers
// is not necessary
graph.getGridLabelRenderer().setHumanRounding(false);
//graph.getGridLabelRenderer().reloadStyles();
}catch(Exception e){
Log.d("BTWeather-error21", e.toString());
}
}
Class FullGraphActivity: Only changes needed were for the grapher call and for hiding/showing the correct view depending on the time call.
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.graph_hour:
time=1;
if(focus==0) {
getSupportActionBar().setTitle(R.string.AllHourly);
try {
GraphView graph2;
graph2 = (GraphView) findViewById(R.id.fullGraph2);
graph2.setVisibility(View.INVISIBLE);
graph2 = (GraphView) findViewById(R.id.fullGraph3);
graph2.setVisibility(View.INVISIBLE);
GraphView graph;
graph = (GraphView) findViewById(R.id.fullGraph);
graph.setVisibility(View.VISIBLE);
gu = new GraphUtility(focus, time, 6, true, true, mainActivity, celsius);
gu.grapher(getApplicationContext(), graph, gu.seriesBuilder(gu.getTempData(gu.getYesterday())),gu.getYesterdayDouble());
} catch (Exception e) {
Log.d("BTWeather-error15", e.toString());
}
}else {
if (focus == 1)
getSupportActionBar().setTitle(R.string.graph_hour_temp);
if (focus == 2)
getSupportActionBar().setTitle(R.string.graph_hour_humid);
if (focus == 3)
getSupportActionBar().setTitle(R.string.graph_hour_wind);
try {
GraphView graph2;
graph2 = (GraphView) findViewById(R.id.fullGraph2);
graph2.setVisibility(View.INVISIBLE);
graph2 = (GraphView) findViewById(R.id.fullGraph3);
graph2.setVisibility(View.INVISIBLE);
GraphView graph;
graph = (GraphView) findViewById(R.id.fullGraph);
graph.setVisibility(View.VISIBLE);
graph.getGridLabelRenderer().resetStyles();
graph.removeAllSeries();
gu = new GraphUtility(focus, time, 6, true, true, mainActivity, celsius);
gu.grapher(getApplicationContext(), graph, gu.seriesBuilder(gu.getTempData(gu.getYesterday())),gu.getYesterdayDouble());
} catch (Exception e) {
Log.d("BTWeather-error15", e.toString());
}
}
return true;
case R.id.graph_day:
time=2;
if(focus==0){
getSupportActionBar().setTitle(R.string.AllDaily);
try {
GraphView graph2;
graph2 = (GraphView) findViewById(R.id.fullGraph);
graph2.setVisibility(View.INVISIBLE);
graph2 = (GraphView) findViewById(R.id.fullGraph3);
graph2.setVisibility(View.INVISIBLE);
GraphView graph;
graph = (GraphView) findViewById(R.id.fullGraph2);
graph.setVisibility(View.VISIBLE);
graph.getGridLabelRenderer().resetStyles();
graph.removeAllSeries();
gu = new GraphUtility(focus, time, 7, true, true, mainActivity, celsius);
gu.grapher(getApplicationContext(), graph, gu.seriesBuilder(gu.getTempData(gu.getWeek())),gu.getWeekDouble());
} catch (Exception e) {
Log.d("BTWeather-error15", e.toString());
}
}else {
if (focus == 1)
getSupportActionBar().setTitle(R.string.graph_day_temp);
if (focus == 2)
getSupportActionBar().setTitle(R.string.graph_day_humid);
if (focus == 3)
getSupportActionBar().setTitle(R.string.graph_day_wind);
try {
GraphView graph2;
graph2 = (GraphView) findViewById(R.id.fullGraph);
graph2.setVisibility(View.INVISIBLE);
graph2 = (GraphView) findViewById(R.id.fullGraph3);
graph2.setVisibility(View.INVISIBLE);
GraphView graph;
graph = (GraphView) findViewById(R.id.fullGraph2);
graph.setVisibility(View.VISIBLE);
graph.getGridLabelRenderer().resetStyles();
graph.removeAllSeries();
gu = new GraphUtility(focus, time, 7, true, true, mainActivity, celsius);
gu.grapher(getApplicationContext(), graph, gu.seriesBuilder(gu.getTempData(gu.getWeek())),gu.getWeekDouble());
} catch (Exception e) {
Log.d("BTWeather-error15", e.toString());
}
}
return true;
case R.id.graph_week:
time=3;
if(focus==0){
getSupportActionBar().setTitle(R.string.AllWeekly);
try {
GraphView graph2;
graph2 = (GraphView) findViewById(R.id.fullGraph);
graph2.setVisibility(View.INVISIBLE);
graph2 = (GraphView) findViewById(R.id.fullGraph2);
graph2.setVisibility(View.INVISIBLE);
GraphView graph;
graph = (GraphView) findViewById(R.id.fullGraph3);
graph.setVisibility(View.VISIBLE);
graph.getGridLabelRenderer().resetStyles();
graph.removeAllSeries();
gu = new GraphUtility(focus, time, 8, false, false, mainActivity, celsius);
gu.grapher(getApplicationContext(), graph, gu.seriesBuilder(gu.getTempData(gu.getMonth())),gu.getMonthDouble());
} catch (Exception e) {
Log.d("BTWeather-error15", e.toString());
}
}else {
if (focus == 1)
getSupportActionBar().setTitle(R.string.graph_week_temp);
if (focus == 2)
getSupportActionBar().setTitle(R.string.graph_week_humid);
if (focus == 3)
getSupportActionBar().setTitle(R.string.graph_week_wind);
try {
GraphView graph2;
graph2 = (GraphView) findViewById(R.id.fullGraph);
graph2.setVisibility(View.INVISIBLE);
graph2 = (GraphView) findViewById(R.id.fullGraph2);
graph2.setVisibility(View.INVISIBLE);
GraphView graph;
graph = (GraphView) findViewById(R.id.fullGraph3);
graph.getGridLabelRenderer().resetStyles();
graph.removeAllSeries();
graph.setVisibility(View.VISIBLE);
gu = new GraphUtility(focus, time, 8, true, true, mainActivity, celsius);
gu.grapher(getApplicationContext(), graph, gu.seriesBuilder(gu.getTempData(gu.getMonth())),gu.getMonthDouble());
} catch (Exception e) {
Log.d("BTWeather-error15", e.toString());
}
}
return true;
}
return false;
}
};
If I find a solution to the multiple views I'll edit this post in case it's useful for someone in the future.
Best,
James
I have tried to add a BarChart in my Code, nothing appear when I launch my app.
The purpose of my code is that: when the user enter the start date (StartDate), end date (EndDate) and the product name, the graph should show the show price evolution during that period.
I have tried the code below, but nothing appear on the graph.
Please help to find the issue, or propose to me another code.
public class ResultProductStatisticsActivity extends AppCompatActivity {
private String mCategory;
private String mName;
private long mStartDate;
private long mEndDate;
private int mNumber = 0;
private ProgressBar mProgressBar;
private ArrayList<ShopDetail> mDetail = new ArrayList<ShopDetail>();
private ArrayList<Float> mPriceList = new ArrayList<Float>();
protected Typeface mTfLight;
private Typeface mTypeFaceLight;
private TextView mMontextViewtest;
private BarChart mChart;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.result_product_statistics_activity);
mChart = (BarChart) findViewById(R.id.m_barchart);
// mChart.setOnChartValueSelectedListener(this);
mChart.setDrawBarShadow(false);
mChart.setDrawValueAboveBar(true);
mChart.setDescription("");
// if more than 60 entries are displayed in the chart, no values will be
// drawn
mChart.setMaxVisibleValueCount(60);
// scaling can now only be done on x- and y-axis separately
mChart.setPinchZoom(false);
mChart.setDrawGridBackground(false);
// mChart.setDrawYLabels(false);
AxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(mChart);
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTypeface(mTfLight);
xAxis.setDrawGridLines(false);
xAxis.setGranularity(1f); // only intervals of 1 day
xAxis.setLabelCount(7);
xAxis.setValueFormatter(xAxisFormatter);
AxisValueFormatter custom = new MyAxisValueFormatter();
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.setTypeface(mTfLight);
leftAxis.setLabelCount(8, false);
leftAxis.setValueFormatter(custom);
leftAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
leftAxis.setSpaceTop(15f);
leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true)
YAxis rightAxis = mChart.getAxisRight();
rightAxis.setDrawGridLines(false);
rightAxis.setTypeface(mTfLight);
rightAxis.setLabelCount(8, false);
rightAxis.setValueFormatter(custom);
rightAxis.setSpaceTop(15f);
rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true)
Legend l = mChart.getLegend();
l.setPosition(Legend.LegendPosition.BELOW_CHART_LEFT);
l.setForm(Legend.LegendForm.SQUARE);
l.setFormSize(9f);
l.setTextSize(11f);
l.setXEntrySpace(4f);
// l.setExtra(ColorTemplate.VORDIPLOM_COLORS, new String[] { "abc",
// "def", "ghj", "ikl", "mno" });
// l.setCustom(ColorTemplate.VORDIPLOM_COLORS, new String[] { "abc",
// "def", "ghj", "ikl", "mno" });
init();
mChart.setMarkerView(new XYMarkerView(this, xAxisFormatter));
}
private void init(){
mCategory = Myrecord.getSearchShopCategory(this);
mName = Myrecord.getSearchShopName(this);
mStartDate = Myrecord.getSearchStartTime(this);
mEndDate = Myrecord.getSearchEndTime(this);
if(mStartDate == -1){
mStartDate = Long.MIN_VALUE;
}
if(mEndDate == -1){
mEndDate = Long.MAX_VALUE;
}
Thread thread = new Thread(){
#Override
public void run() {
MyDB db = new MyDB(ResultProductStatisticsActivity.this);
ArrayList<MyDetail> detailList = db.getMyDetailByAll(mCategory, mName, -1, 0, -1);
for(int i = 0; i < detailList.size(); i ++){
MyDetail detail = detailList.get(i);
long date = detail.date;
if(date >= mStartDate && date <= mEndDate){
mPriceList.add(db.getPriceGoodsByOwnName("ALEVONS")+0f);
}
}
ResultProductStatisticsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
setData(mPriceList);
}
});
}
};
thread.start();
}
private void setData(ArrayList<Float> mPriceList) {
mChart.getXAxis().setAxisMinValue(mStartDate);
mChart.getXAxis().setAxisMaxValue(mEndDate);
ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>();
for (int i = 0; i < mPriceList.size(); i++) {
yVals1.add(new BarEntry(i , mPriceList.get(i)));
}
BarDataSet set1;
if (mChart.getData() != null &&
mChart.getData().getDataSetCount() > 0) {
set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0);
set1.setValues(yVals1);
mChart.getData().notifyDataChanged();
mChart.notifyDataSetChanged();
} else {
set1 = new BarDataSet(yVals1, "Evolution du prix produit");
set1.setColors(ColorTemplate.MATERIAL_COLORS);
ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
dataSets.add(set1);
BarData data = new BarData(dataSets);
data.setValueTextSize(10f);
data.setValueTypeface(mTfLight);
data.setBarWidth(0.9f);
mChart.setData(data);
}
}
}
A wild guess, without any more details provided: your're setting the x-axis min and max values to the start and end date. I'm guessing this is encoded in unix time, so you have something like 1470614400 and 1471219200.
Now looking at your data, it will start with 0 and go up to the number of prices you have in your price list (mPriceList.size()). So with 10 prices we'd have values at 0 through 9. However, since your x-axis starts at 1470614400, no data will be shown (although the axis, gridlines etc. should be visible).
So in order to fix your code (depending on how your price list is structured, this example assumes one price every hour), you'd need to change your code in setData to this:
for (int i = 0; i < mPriceList.size(); i++) {
yVals1.add(new BarEntry(mStartDate + i * 3600, mPriceList.get(i)));
}
If you have a list of dates associated with the price values, you can also simply do this:
for (int i = 0; i < mPriceList.size(); i++) {
yVals1.add(new BarEntry(mDateList.get(i), mPriceList.get(i)));
}
We the reply of(#TR4Android),
I have update my code such below and I can get the graph:
float start = 0f;
mChart.getXAxis().setAxisMinValue(start);
mChart.getXAxis().setAxisMaxValue(mPriceList.size());
for (int i = 0; i < mPriceList.size(); i++) {
yVals1.add(new BarEntry(i , mPriceList.get(i)));
}
But I have a bit issue with start date end date where each item has been bought. I have put each date in array list but I don't see how I can put it on xAxis. The Array list is :
private ArrayList<Long> mDateList = new ArrayList<Long>();
One example of mDateList value is 2016/08/13
I'm trying to follow this guide:
https://github.com/PhilJay/MPAndroidChart/wiki/Setting-Data
It has the line of code:
LineData data = new LineData(xVals, dataSets);
When I tried it in my AndroidStudio, the LineData() constructor only takes 1 argument instead of 2 arguments as shown in the guide.
Anyone know how to initialize with the new version of MPAndroidChart ?
I have the following in my gradle setting:
compile 'com.github.PhilJay:MPAndroidChart:v3.0.0-beta1'
Maybe I should drop to 2.2.5 ?
Update
Yes, I changed gradle to use 2.2.5 and now LineData() constructor has multiple parameters as expected.
Docs needs updating for version 3.0.
in this version
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
try it
public class MainActivity extends AppCompatActivity {
private LineChart lc;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
public int ran() {
Random ran = new Random();
int i = ran.nextInt(199);
return i;
}
public int ran2() {
Random ran = new Random();
int i = ran.nextInt(49);
return i;
}
public void initData() {
lc.setExtraOffsets(12,50,24,0); //padding
setDescription("two lines example");
lc.animateXY(500, 0);
setLegend();
setYAxis();
setXAxis();
setChartData();
}
public void setLegend() {
Legend legend = lc.getLegend();
legend.setForm(Legend.LegendForm.LINE);
legend.setFormSize(20);
legend.setTextSize(20f);
legend.setFormLineWidth(1);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
legend.setTextColor(Color.BLACK);
}
public void setDescription(String descriptionStr) {
Description description = new Description();
description.setText(descriptionStr);
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
Paint paint = new Paint();
paint.setTextSize(20);
float x = outMetrics.widthPixels - Utils.convertDpToPixel(12);
float y = Utils.calcTextHeight(paint, descriptionStr) + Utils.convertDpToPixel(12);
description.setPosition(x, y);
lc.setDescription(description);
}
public void setYAxis() {
final YAxis yAxisLeft = lc.getAxisLeft();
yAxisLeft.setAxisMaximum(200);
yAxisLeft.setAxisMinimum(0);
yAxisLeft.setGranularity(10);
yAxisLeft.setTextSize(12f);
yAxisLeft.setTextColor(Color.BLACK);
yAxisLeft.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
return value == yAxisLeft.getAxisMinimum() ? (int) value + "" : (int) value +"";
}
});
lc.getAxisRight().setEnabled(false);
}
public void setXAxis() {
XAxis xAxis = lc.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(false);
xAxis.setLabelCount(20);
xAxis.setTextColor(Color.BLACK);
xAxis.setTextSize(12f);
xAxis.setGranularity(1);
xAxis.setAxisMinimum(0);
xAxis.setAxisMaximum(100);
xAxis.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
return value == 0 ? "example" : (int) value + "";
}
});
}
public void setChartData() {
List<Entry> yVals1 = new ArrayList<>();
for (int i = 0; i < 100; i++) {
int j = ran();
yVals1.add(new Entry(1 + i,j));
}
List<Entry> yVals2 = new ArrayList<>();
for (int i = 0; i < 100; i++) {
int j = ran2();
yVals2.add(new Entry(1 + i,j));
}
LineDataSet lineDataSet1 = new LineDataSet(yVals1, "ex1");
lineDataSet1.setValueTextSize(20);
lineDataSet1.setDrawCircleHole(true);
lineDataSet1.setColor(Color.MAGENTA);
lineDataSet1.setMode(LineDataSet.Mode.LINEAR);
lineDataSet1.setDrawCircles(true);
lineDataSet1.setCubicIntensity(0.15f);
lineDataSet1.setCircleColor(Color.MAGENTA);
lineDataSet1.setLineWidth(1);
LineDataSet lineDataSet2 = new LineDataSet(yVals2, "ex2");
lineDataSet2.setValueTextSize(20);
lineDataSet2.setDrawCircleHole(true);
lineDataSet2.setColor(Color.BLUE);
lineDataSet2.setMode(LineDataSet.Mode.LINEAR);
lineDataSet2.setDrawCircles(true);
lineDataSet2.setCubicIntensity(0.15f);
lineDataSet2.setCircleColor(Color.BLUE);
lineDataSet2.setLineWidth(1);
.
.
.
ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
dataSets.add(lineDataSet1);
dataSets.add(lineDataSet2);
LineData lineData = new LineData(dataSets);
lc.setVisibleXRangeMaximum(5);
lc.setScaleXEnabled(true);
lc.setData(lineData);
}
and like this.
Version 3.0 is initialized like so:
LineChart lineChart = new LineChart(context);
lineChart.setMinimumHeight(ToolBox.dpToPixels(context, 300));
lineChart.setMinimumWidth(ToolBox.getScreenWidth());
ArrayList<Entry> yVals = new ArrayList<>();
for(int i = 0; i < frigbot.getEquipment().getTemperatures().size(); i++)
{
Temperature temperature = frigbot.getEquipment().getTemperatures().get(i);
yVals.add(new Entry(
i, temperature.getValue().floatValue()
));
}
LineDataSet dataSet = new LineDataSet(yVals, "graph name");
dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
dataSet.setCubicIntensity(0.2f);
LineData data = new LineData(dataSet);
lineChart.setData(data);
It appears we can't specify custom horizontal labels, LineChart itself will automatically generate the horizontal and vertical axis labelling.
I'm finding it a bit difficult to figure out how to implement time in the X Axis of a graph in Android?
This is my code:
for (int i = 0; i < listSize; i++)
{
String[] onlyReading = mData.get(i).getReading().split(" ");
readingList[i] = Double.parseDouble(onlyReading[0]);
String date = mData.get(i).getUnFormatedDate();
String[] temp = date.split(" ");
String[] dateTemp = null;
String[] timeTemp = null;
if(temp.length > 0)
{
dateTemp = temp[0].trim().split("-");
timeTemp = temp[1].trim().split(":");
Date dateObj = new Date();
String year = "0";
if(dateTemp != null)
{
dateObj.setDate(Integer.parseInt(dateTemp[0]));
dateObj.setMonth(Integer.parseInt(dateTemp[1]) - 1);
year = dateTemp[2].trim();
if(dateTemp[2].trim().length() == 4)
{
year = dateTemp[2].substring(2, 4);
}
dateObj.setYear(Integer.parseInt(year)+100);
}
if(timeTemp != null)
{
calendar = new GregorianCalendar(Integer.parseInt(year) + 2000, Integer.parseInt(dateTemp[1]) - 1, Integer.parseInt(dateTemp[0]), Integer.parseInt(timeTemp[0]), Integer.parseInt(timeTemp[1]));
}
dateObj = new Date(calendar.getTimeInMillis());
dateList[i] = dateObj;
}
}
if(dateList.length > 0)
{
//dates.clear();
//values.clear();
//readingData.clear();
//readingDate.clear();
GraphViewData[] data = new GraphViewData[dateList.length];
LineGraphView graphView = new LineGraphView(
getActivity() // context
, "" // heading
);
for (int i = 0; i < listSize; i++)
{
data[i] = new GraphViewData(Double.valueOf(i), readingList[i]);
}
GraphViewSeries exampleSeries = new GraphViewSeries(data);
graphView.addSeries(exampleSeries);
graphView.setDrawBackground(false);
((LineGraphView) graphView).setDrawDataPoints(true);
graphView.getGraphViewStyle().setGridColor(0);
graphView.getGraphViewStyle().setHorizontalLabelsColor(Color.WHITE);
graphView.getGraphViewStyle().setVerticalLabelsColor(Color.WHITE);
graphView.getGraphViewStyle().setNumHorizontalLabels(5);
graphView.getGraphViewStyle().setNumVerticalLabels(5);
graphView.setManualYAxisBounds(400, 0);
mGraphParent.addView(graphView);
}
}
Even though I add the Y axis values, I'm not able to figure out how to add time values to the X-axis?
I know it is an old question, but I solved by using DefaultLabelFormatter().
graphView.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter() {
#Override
public String formatLabel(double value, boolean isValueX) {
if (isValueX) {
Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return formatter.format(value);
}
return super.formatLabel(value, isValueX);
}
});
Based on the following video:
https://www.youtube.com/watch?v=xt8gx7Z7yJU
the trick is to just convert the time to seconds or milliseconds (unix time) and you it as X-value.
There's an example on the GraphView-Demos project. Take a look at:
https://github.com/jjoe64/GraphView-Demos/blob/master/src/com/jjoe64/graphviewdemos/CustomLabelFormatterActivity.java#L68
I had the same issue. The easiest method was to convert Time into milliseconds. Using a Gregorian Calendar might be more helpful as the methods in Date are deprecated.
Calendar cal=new GregorianCalendar(2014,6,12,9,30,0);
data[i]=new GraphViewData(cal.getTimeInMillis,VALUE);
Then set the CustomLabelFormatter.
graphView.setCustomLabelFormatter(new CustomLabelFormatter() {
#Override
public String formatLabel(double value, boolean isValueX) {
// TODO Auto-generated method stub
if (isValueX) {
Date d = new Date((long) (value));
return (dateFormat.format(d));
}
return "" + (int) value;
}
});
Time/Date appears in the format specified in dateFormat.