how to make androidplot axis caption visible - android

Could somebody please explain me what I have to do so that my plot shows me at least any kind of axis caption? The horrible androidplot documentation explains less than nothing.
Code:
Date day1 = getDate(28, MAY, 2016);
Date day2 = getDate(29, MAY, 2016);
Date day3 = getDate(30, MAY, 2016);
Date day4 = getDate(31, MAY, 2016);
Date day5 = getDate(1, JUNE, 2016);
Number[] quotes = new Float[]{4.23f, 5.13f, 5.73f, 6.12f, 4.23f};
Number[] dates = new Long[]{day1.getTime(), day2.getTime(), day3.getTime(), day4.getTime(), day5.getTime(),};
XYSeries series = new SimpleXYSeries(Arrays.asList(dates), Arrays.asList(quotes), "History 5 days");
LineAndPointFormatter formatter = new LineAndPointFormatter();
formatter.setPointLabelFormatter(new PointLabelFormatter());
formatter.configure(this, R.xml.line_point_formatter_with_labels);
plot.setDomainStep(XYStepMode.SUBDIVIDE, 5);
plot.setRangeStep(XYStepMode.SUBDIVIDE, 5);
plot.setDomainValueFormat(new Format()
{
private SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.");
#Override
public StringBuffer format(Object object, StringBuffer buffer, FieldPosition field)
{
long millis = ((Number) object).longValue();
Date date = new Date(millis);
return dateFormat.format(date, buffer, field);
}
#Override
public Object parseObject(String string, ParsePosition position)
{
return null;
}
});
plot.addSeries(series, formatter);
Plot xml:
<com.androidplot.xy.XYPlot
android:id="#+id/plot"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="10dp"
app:domainLabel="domain label"
app:label="A simple plot"
app:rangeLabel="range label" />
There couldnĀ“t be less caption:
at the left side I would like to have numbers like 4.0, 5.0, 6.0 and at the bottom the date

Looks like you arent applying any styling in your XML. If you check out the xml example in the Androidplot quickstart you'll notice it has a style applied like so:
<com.androidplot.xy.XYPlot
style="#style/APDefacto.Dark"
android:id="#+id/plot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
ap:label="A Simple XY Plot"
ap:rangeLabel="range"
ap:domainLabel="domain"/>
The key attribute is style="#style/APDefacto.Dark", which basically applies a canned set of attrs to your plot to make it pretty. There's also a link in the doc to the full list of custom attrs if you prefer to come up with your own layout.
In any case applying the above style should solve the immediate problem you are having :-)

Related

MPAndroidChart x date value duplication problem

I am implementing the function to display the change of exercise time by date as a graph.
But there was a problem.
Before I explain the problem, I will briefly explain my code.
When a date is input from the user, the date is stored in the database and output by date.
For example, when the user enters 2020/06/26, it is displayed as 06/26 on the graph.
Now I will explain the problem.
The x value of the graph is overlapping. 07/01 does not appear immediately after 06/30, but very far.
I will attach my code and execution result. enter image description here
xAxis.setValueFormatter(new ValueFormatter() {
#Override
public String getFormattedValue(float value) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyMMdd");
Date date = null;
try {
date = simpleDateFormat.parse(Float.toString(value));
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat newFormat = new SimpleDateFormat("MM/dd");
String dateString = newFormat.format(date);
return dateString;
}
});
Hard to tell from the code you provide. But most probably, the problem does not lie in the ValueFormatter, but in the actual x values you use. Having x values in the format yyMMdd ist most likely not what you want, because the difference between e.g. 2020-04-01 and 2020-04-02 is not the same as between 2020-03-31 and 2020-04-01, event if it should be exactly the same (1 day). You should use another representation for the x values, e.g. "days since 1970".
This still does not explain why 06-30 is displayed after 07-01 and even after 08-19, however. My guess is that your Entry list is not sorted properly in ascending order.

Androidplot background, start, end values and ranges

I am trying to create a custom XYPlot with Androidplot but can't seem to fully configure it.
This is my code:
XYSeries series = new SimpleXYSeries(Arrays.asList(dates), Arrays.asList(times), "Time on level");
// Create a formatter to use for drawing a series using LineAndPointRenderer:
LineAndPointFormatter formatter = new LineAndPointFormatter(Color.rgb(0, 100, 0), Color.rgb(0, 100, 0), null, new PointLabelFormatter(Color.BLUE));
totalTimePlot.setRangeValueFormat(new DecimalFormat("#.#"));
totalTimePlot.setGridPadding(0, 0, 0, 200);
totalTimePlot.setBackgroundColor(Color.WHITE);
totalTimePlot.getGraphWidget().getBackgroundPaint().setColor(Color.WHITE);
totalTimePlot.getGraphWidget().getGridBackgroundPaint().setColor(Color.WHITE);
totalTimePlot.getGraphWidget().getDomainOriginLinePaint().setColor(Color.BLACK);
totalTimePlot.getGraphWidget().getRangeOriginLinePaint().setColor(Color.BLACK);
totalTimePlot.setTicksPerDomainLabel(1);
totalTimePlot.setRangeStepValue(10);
totalTimePlot.getGraphWidget().setDomainLabelOrientation(-90);
totalTimePlot.setMarkupEnabled(false);
totalTimePlot.setBorderStyle(Plot.BorderStyle.SQUARE, null, null);
totalTimePlot.setDomainValueFormat(new Format() {
SimpleDateFormat sdf = new SimpleDateFormat("EEE(MM.dd)-HH:mm:ss");
#Override
public StringBuffer format(Object object, StringBuffer buffer, FieldPosition field) {
long timestamp = ((Number) object).longValue();
Date date = new Date(timestamp);
return sdf.format(date, buffer, field);
}
#Override
public Object parseObject(String string, ParsePosition position) {
return null;
}
});
totalTimePlot.getGraphWidget().setPaddingLeft(4);
totalTimePlot.addSeries(series, formatter);
And this is the end result:
As you can see this is very ugly. Can you help me at least configure it so that the Range labels are displayed. I would also like to know how to make the background white as well as have the first and last "ticks" visible.
Thank you.
EDIT:
I managed to include the first and last value by setting the boundaries. But the other problems remain.
Agreed it's pretty ugly :-) It would be easier to give you suggestions if you list a few specific items you'd like to improve. Having said that, here's a few things I would start with:
Use the DemoApp's SimpleXYPlotActivity xml style as a starting point. This should fix your margin issues and improve the overall appearance.
Simplify your date/time format for your domain labels. Maybe something like day/month hour:minute. I don't know your exact use case so maybe you require the format you're using.
Get rid of the dark background that frames your plot.
Consider using the CatmullRomInterpolator to draw a smooth line.

Android Graphview changing x axis data

in my app I'm using GraphView library to create a LineGraphView. It shows data from specified dates from example from 18.01 to 30.01. When I change the boundaries for example from 25.01 to 29.01 GraphView updates the chart (cuts not needed lines) but still shows wrong x axis data (18.01 to 30.01), however when user starts to interact with chart (zooming, scrolling) it updates it's x axis and everything is fine. Is there a method to force GraphView to update it's x axis? I have only encountered this problem if user has been interacting with chart (zooming, scrolling) before changing dates if there was no interaction graphview updates properly. I'm creating charts this way:
Inside onCreate:
mGraphView = new LineGraphView(this, "Temperature Measurements");
And a function to create a chart when I fetch data from database:
public void createChart(Cursor cursor) {
GraphViewData[] values = new GraphViewData[cursor.getCount()];
while (cursor.moveToNext()) {
String time = cursor.getString(cursor
.getColumnIndex(MeasurementEntry.DATE_IN_MINUTES));
String temp = cursor.getString(cursor
.getColumnIndex(MeasurementEntry.TEMPERATURE));
values[cursor.getPosition()] = new GraphViewData(
Double.parseDouble(time), Double.parseDouble(temp));
}
mGraphView.removeAllSeries();
mGraphView.addSeries(new GraphViewSeries(values));
mGraphView.setScalable(true);
mGraphView.getGraphViewStyle().setTextSize(15);
final SimpleDateFormat formatter = new SimpleDateFormat(
"dd.MM.yyyy HH:mm");
mGraphView.setCustomLabelFormatter(new CustomLabelFormatter() {
#Override
public String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return formatter.format(new Date((long) value));
}
return null;
}
});
}
And here is the screenshot with the problem:
OK, so I made it however I think it can be done better, what I done is removing graphView from parent layout, creating new graphview and adding new graphview - I do this sequence everytime user is changing the boundaries. Maybe it will help somebody (short snippet of createChart method, container is my parent layout):
container.removeView(mGraphView);
mGraphView = new LineGraphView(this, "Temperature Measurements");
container.addView(mGraphView);
mGraphView.removeAllSeries();
mGraphView.addSeries(new GraphViewSeries(values));
mGraphView.setScalable(true);
mGraphView.getGraphViewStyle().setTextSize(15);

why my code is so slow?

i runing this code on android after load a cursor with the query i pass to the adapter, but my date is in long in milliseconds format so i need to format properly before load the adapter!
problem is this code is taking 14 seconds to pass a 50 items load, the problem get worst if i call it inside the adapter getView cause get slow when i scrool, if i take this function out the program runs smoothly
this is call inside my listfragment
private String dateFormatPatternEdited(long timeMS) {
android.text.format.DateFormat df = new android.text.format.DateFormat();
final Calendar eDate = Calendar.getInstance();
Calendar sDate = Calendar.getInstance();
sDate.setTimeInMillis(timeMS);
long daysBetween = 0;
while (sDate.before(eDate)) {
sDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
String mDateFormatPattern = FuelTrackerApplication.dateFormat.format(timeMS);
if (daysBetween < 2){
mDateFormatPattern = FuelTrackerApplication.timeFormat.format(timeMS);
} else if(daysBetween < 365){
mDateFormatPattern = df.format(FuelTrackerApplication.dateFormatPattern,timeMS).toString();
}
return mDateFormatPattern;
}
and this is were i initialize the date formats i gonna use its called inside onCreate in FuelTrackerApplication i dont think theres nothing wrong with this
public void initializeDateFormat() {
android.text.format.DateFormat df = new android.text.format.DateFormat();
dateFormatPattern = "MMM dd";
if (android.os.Build.VERSION.SDK_INT >= 18){
dateFormatPattern = df.getBestDateTimePattern(Locale.getDefault(), dateFormatPattern);
}
dateFormat = df.getMediumDateFormat(getApplicationContext());
timeFormat = df.getTimeFormat(getApplicationContext());
dateFormat2 = df.getLongDateFormat(getApplicationContext());
}
Ok just a few things. Depending on how long ago your dates are going back. You are only interested if the days between go more then 365. So if your dates are going back for years, you're doing extra work.
while (sDate.before(eDate) && daysBetween <= 365) {
sDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
Will let it break, it means if you have 20 entries going back 5 years, you don't do so much work.
It might be worth while to possibly just check the milliseconds difference. I'm not sure if this is precise enough, but it should work. It means you don't need to loop everything E.g
long millisecondsToday = getMilliseconds;
long timeMs = // you already have this
long millisecondsDifference = millisecondsToday - timeMs;
if (millisecondsDifference < MILLISECONDS_TWO_DAYS) // set a final variable out of this method
// etc
If might also be worth while initialising some of your variables once outside of the method. Like your df, that is being created 50 times, and then just having something set on it. Same with your eDate.
i got this incredible faster and practicaly remove the hole function
instead goes like this
lDateBetween = NOW - timeMS;
if (lDateBetween < DAY)
return FuelTrackerApplication.timeFormat.format(timeMS);
else if (lDateBetween < YEAR)
return df.format(FuelTrackerApplication.dateFormatPattern,timeMS).toString();
else return FuelTrackerApplication.dateFormat.format(timeMS);
all calculation is made using milliseconds i also put 2 final NOW and YEAR, also df and lDateBetween
i think is the fastest i can get!

I cannot print more than 25 dates, it somehow goes crazy and continues from another date, why?

I have a datepicker, and I pick up two dates, like 2012-04-08 and 2012-05-11. Because I have a database and need store dates as strings I convert them to 20120408 and 20120511 (strings so far). My code contains the next steps. I call my function with these strings:
public void durva(String datefrom, String dateto) throws ParseException {
datefrom = GlobalVars.getDateStringFrom();
dateto = GlobalVars.getDateStringTo();
Log.i("DateFrom", datefrom);
Log.i("Dateto", dateto);
SimpleDateFormat formatter2 = new SimpleDateFormat("yyyyMMdd"); //-de most yyMMdd
formatter2.setLenient(false);
Date dates1;
Date dates2;
long mili1;
long mili2;
long diff;
String dates="";
String convertedDates = "";
dates1 = formatter2.parse(datefrom);
mili1 = dates1.getTime();
Log.i("date1", String.valueOf(mili1));
dates2 = formatter2.parse(dateto);
mili2 = dates2.getTime();
Log.i("date2", String.valueOf(mili2));
diff = 1+((mili2-mili1)/86400000);
Log.i("diff", String.valueOf(diff));
long [] millis = new long[(int) diff];
for (int i=0;i<diff;i++)
{
millis[i] = mili1+(86400000*i);
Log.i("millii", String.valueOf(millis[i]));
dates = dates + String.valueOf(millis[i]) + " ";
SimpleDateFormat formatterX = new SimpleDateFormat("yyyyMMdd");
String dateString = formatterX.format(new Date(millis[i]));
convertedDates = convertedDates + dateString + " ";
}
Log.i("DATES", convertedDates);
}
I use the a created GlobalVars when I pick a date and covert them to this string format I mentioned above. Then I convert them to millisecs. Then I convert them back to my format but it is not important, since the millisecs are already messed up. With
for (int i=0;i<diff;i++)
{
millis[i] = mili1+(86400000*i);
Log.i("millii", String.valueOf(millis[i]));
I always increase the millisecs, but what happens after the 25th value? It travels back in time and continues from another value! In this example I get: 20120408 20120409 .. 20120502 20120314..20120322 . I add 86400000 (millisecs per day) for jumping a whole day.
What's happening here?
Thank you in advance!
You should use 86400000L, or declare i as long:
millis[i] = mili1+(86400000L*i);
Otherwise both i and 86400000 are 32 bit integers, so the result is calculated as a 32-bit integer. Unfortunately 86400000*25 is too big to fit in 32 bits, so it wraps around.
86400000*25 is -2134967296.
Another thing you should be careful about is that not all days have 24 hours thanks to DST.

Categories

Resources