I have a problem when i set value from sqlite to x-axis label.
this is the picture
And my code of X-axis forrmated is
Axis.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
String selectQueryz = "SELECT * FROM table_palembang";
db = new DBHelper(getApplicationContext());
SQLiteDatabase dbz = db.getWritableDatabase();
Cursor cursorz = dbz.rawQuery(selectQueryz, null);
countz = cursorz.getCount();
String[] datez = new String[countz];
ArrayList<String> arral = new ArrayList<>();
for (int k = 0; k < countz; k++) {
cursorz.moveToNext();
datez[k] = cursorz.getString(2);
arral.add(datez[k]);
}
return datez[countz % arral.size()];
}
});
can anyone help me?
thanks ...
ValueFormatter is used to format your data which you set with chart.setData() not to set data itself.
Here is sample code how to format dates
xAxis.setValueFormatter(new IAxisValueFormatter() {
private final SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm", Locale.ENGLISH);
#Override
public String getFormattedValue(float value, AxisBase axis) {
long millis = TimeUnit.HOURS.toMillis((long) value);
return mFormat.format(new Date(millis));
}
});
EDIT
I just took a look that you store indices of date array to chart data. If so, you just need to return date from dates array.
String[] datez;
String selectQueryz = "SELECT * FROM table_palembang";
db = new DBHelper(getApplicationContext());
SQLiteDatabase dbz = db.getWritableDatabase();
Cursor cursorz = dbz.rawQuery(selectQueryz, null);
countz = cursorz.getCount();
datez = new String[countz];
for (int k = 0; k < countz; k++) {
cursorz.moveToNext();
datez[k] = cursorz.getString(2);
}
xAxis.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
return datez[(int) value];
}
});
P.S. DataBase calls should be in background thread.
Related
I need to get the count of records for the current day, from the database. The entries in the Firebase Realtime are in timestamp, I parse them using SimpleDateFormat.
But I could not get the count of records, for example, for today's date. Tell me what to do? Thanks
IMAGE RECORDS IN FIREBASE REALTIME
private void fetchDataWaterCount() {
currDate = null;
String uid = firebaseAuth.getUid();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
currDate = LocalDate.now().toString();
}
waterRef = FirebaseDatabase.getInstance().getReference("Users").child(uid).child("body").child("water");
waterRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
for (DataSnapshot ds : snapshot.getChildren()) {
waterModel = ds.getValue(WaterModel.class);
waterArray.add(waterModel);
waterModel.setWaterModelList(waterArray);
ArrayList listDate = new ArrayList();
for (int i = 0; i < waterModel.getWaterModelList().size(); i++) {
long dateList = waterModel.getWaterModelList().get(i).getDate();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
String dateFormat = formatter.format(new Date(dateList));
listDate.add(dateFormat);
if(listDate.contains(currDate)){
int water_count = (int) listDate.size();
drawable = getActivity().getDrawable(R.drawable.circut_progress_bar);
progressBar.setProgress(water_count);
progressBar.setMax(12);
progressBar.setSecondaryProgress(water_count);
progressBar.setProgressDrawable(drawable);
textViewWaterCount.setText(String.valueOf(water_count));
if (water_count >= 12) {
textViewWaterCount.setText("Done");
textViewWaterCount.setTextColor(getResources().getColor(R.color.colorGreen_900));
drawable = getActivity().getDrawable(R.drawable.circut_progressbar_green);
progressBar.setProgressDrawable(drawable);
}
}
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
If you want to know the amount of WaterModels that match a specific date then you need to count them as they appear.
You are currently adding every date to the list regardless if it matches the currDate, so your count is the total dates not the specific amount of specific dates.
//Add this
int dateCount = 0;
for (int i = 0; i < waterModel.getWaterModelList().size(); i++) {
long dateList = waterModel.getWaterModelList().get(i).getDate();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
String dateFormat = formatter.format(new Date(dateList));
listDate.add(dateFormat);
//Add this
if(dateFormat == currDate){
dateCount++;
}
//I don't know what your doing here but this will return true
//if there is at least 1 match. You can't use this to track how many dates
//match
if (listDate.contains(currDate)) {
int water_count = (int) listDate.size();
drawable = getActivity().getDrawable(R.drawable.circut_progress_bar);
progressBar.setProgress(water_count);
progressBar.setMax(12);
progressBar.setSecondaryProgress(water_count);
progressBar.setProgressDrawable(drawable);
textViewWaterCount.setText(String.valueOf(water_count));
if (water_count >= 12) {
textViewWaterCount.setText("Done");
textViewWaterCount.setTextColor(getResources().getColor(R.color.colorGreen_900));
drawable = getActivity().getDrawable(R.drawable.circut_progressbar_green);
progressBar.setProgressDrawable(drawable);
}
}
}
dateCount will contain the total amount of Dates that match the currDate.
Hi I am using MPAndroid chart as charting library in my android app. I am trying to highlight some out of the range values on line dataset with different color (Picture 1)and if the value is beyond range then I want to also change marker-view drawable image also.
I have achieved this (Picture 2 ) for now I have managed to change color to red of out of the range values. How can I achieve Picture 1 in chart?
private void populateChart() {
chart = binding.lcCharts;
chart.setBackgroundColor(Color.WHITE);
chart.getDescription().setEnabled(false);
chart.setDoubleTapToZoomEnabled(false);
chart.setPinchZoom(false);
chart.setScaleEnabled(false);
getXAxisData()
LineData lineData = new LineData(setLineDataSet());
lineData.setDrawValues(false);
chart.setData(lineData);
chart.setTouchEnabled(true);
chart.setDrawMarkers(false);
chart.setHighlightPerTapEnabled(true);
chart.setMarker(new YourMarkerView(fragment.requireContext(), R.layout.layout_pop_up));
chart.setClipChildren(false);
chart.setClipToPadding(false);
chart.invalidate();
chart.notifyDataSetChanged();
}
private ArrayList<ILineDataSet> setLineDataSet() {
ArrayList<ILineDataSet> dataSet = new ArrayList<>();
for (int i = 0; i < response.size(); i++) {
LineDataSet lineDataSet = new LineDataSet(setData(i),
response.get(i).getName());
lineDataSet.setLineWidth(3);
lineDataSet.setColor(this.getResources().getColor(colorArray[i]));
lineDataSet.setDrawCircleHole(false);
lineDataSet.setCircleRadius(4);
lineDataSet.setCircleColors(setColorOfLineDataSet(i));
dataSet.add(lineDataSet);
}
return dataSet;
}
private ArrayList<Integer> setColorOfLineDataSet(int i) {
ArrayList<Integer> color = new ArrayList<Integer>();
for (int j = 0; j < response.get(i).size(); j++) {
if (!response.get(i).isNormal()) {
color.add(R.color.Red);
} else {
color.add(colorArray[i]);
}
}
return color;
} private void getXAxisData() {
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawAxisLine(false);
xAxis.setDrawGridLines(false);
// xAxis.setGranularity(1f);
xAxis.setValueFormatter(new MyXAxisValueFormatter(getDateArrayForXAxis()));//getDateArrayForXAxis function returns a String array of size 14 with values of dates of past two weeks.
xAxis.setLabelCount(14, true);
}
public class MyXAxisValueFormatter extends ValueFormatter {
private String[] mValues;
public MyXAxisValueFormatter(String[] values) {
this.mValues = values;
}
public String getFormattedValue(float value) {
String val = null;
try {
val = String.valueOf(mValues[(int) value]);
} catch (IndexOutOfBoundsException e) {
}
return val;
}
/**
* Used to draw axis labels, calls {#link #getFormattedValue(float)} by default.
*
* #param value float to be formatted
* #param axis axis being labeled
* #return formatted string label
*/
public String getAxisLabel(float value, AxisBase axis) {
return getFormattedValue(value);
}
}
This code is crashing with arrayIndexOutOfBoundException.
enter code here
For customizing the Circle shape you can use following methods of the LineDataSet:
setCircleColor(/some Color value/)
setCircleRadius(/* some float value */)
setDrawCircleHole(/* boolean value */)
setDrawFilled(/* boolean value*/)
try these out, maybe you'll find something which you want. But I don't think it will allow you to change the shape completely.
I have referred to this article for an example:https://www.studytutorial.in/android-line-chart-or-line-graph-using-mpandroid-library-tutorial
I have this database iterator that iterates through Firebase database and gets all the values and displays them in a recyclerview. Inside the loop i add an if condition that checks to filter all the values with a certain condition...The positive part works very well.Am wondering how can i get the exception where no items meet that condition.For now nothing happens.
mUsersDatabaseReference.addValueEventListener(new
ValueEventListener() {
#Override
public void onDataChange (DataSnapshot dataSnapshot){
int count = 0;
Iterator<DataSnapshot> items = dataSnapshot.getChildren().iterator();
while (items.hasNext()) {
DataSnapshot item = items.next();
//Define the names of the values to be picked
String theName;
String theImage;
String from;
String to;
String price;
String time;
String id;
if (item.child("DepartureLatitude").exists() && item.child("DestinationLongitude").getValue() != null) {
//Define the variables
theName = item.child("name").getValue().toString();
from = item.child("DepartureLocation").getValue().toString();
to = item.child("DestinationLocation").getValue().toString();
price = item.child("TripPrice").getValue().toString();
time = item.child("DepartureTime").getValue().toString();
theImage = item.child("DriverImage").getValue().toString();
String get = item.child("DriverImage").getRef().getParent().toString();
id = get.substring(get.lastIndexOf("/") + 1);
//Driver Depature
Double deplat = Double.valueOf(item.child("first").getValue().toString());
Double deplong = Double.valueOf(item.child("second").getValue().toString());
Double first = deplat * deplong;
//Driver destination
Double destlat = Double.valueOf(item.child("DestinationLatitude").getValue().toString());
Double destlong = Double.valueOf(item.child("DestinationLongitude").getValue().toString());
Double sec = deplong * deplat;
if (first <= distance && sec <= distance && item.child("DepartureDay").getValue().toString().equals(name)) {
UserDB entry = new UserDB(theName, from, to, price, time, theImage, id);
entries.clear();
entries.add(entry);
mRecyclerview.setAdapter(new RecUsersAdapter(getActivity(), entries));
findingLocation.dismiss();
}
} else {
message = "Sorry! Some records are missing";
String reason = message;
Toast.makeText(view.getContext(), reason, Toast.LENGTH_SHORT).show();
}
}
mUsersDatabaseReference.removeEventListener(this);
}
#Override
public void onCancelled (DatabaseError databaseError){
String reason = databaseError.getMessage().toString();
Toast.makeText(view.getContext(), reason, Toast.LENGTH_SHORT).show();
}
});
you have two conditions which one is filtering your values ?
#edit you need it to be in the inner if condition
try this
while (items.hasNext()) {
DataSnapshot item = items.next();
//Define the names of the values to be picked
String theName;
String theImage;
String from;
String to;
String price;
String time;
String id;
if (item.child("DepartureLatitude").exists() && item.child("DestinationLongitude").getValue() != null) {
//Define the variables
theName = item.child("name").getValue().toString();
from = item.child("DepartureLocation").getValue().toString();
to = item.child("DestinationLocation").getValue().toString();
price = item.child("TripPrice").getValue().toString();
time = item.child("DepartureTime").getValue().toString();
theImage = item.child("DriverImage").getValue().toString();
String get = item.child("DriverImage").getRef().getParent().toString();
id = get.substring(get.lastIndexOf("/") + 1);
//Driver Depature
Double deplat = Double.valueOf(item.child("first").getValue().toString());
Double deplong = Double.valueOf(item.child("second").getValue().toString());
Double first = deplat * deplong;
//Driver destination
Double destlat = Double.valueOf(item.child("DestinationLatitude").getValue().toString());
Double destlong = Double.valueOf(item.child("DestinationLongitude").getValue().toString());
Double sec = deplong * deplat;
if (first <= distance && sec <= distance && item.child("DepartureDay").getValue().toString().equals(name)) {
UserDB entry = new UserDB(theName, from, to, price, time, theImage, id);
entries.clear();
entries.add(entry);
mRecyclerview.setAdapter(new RecUsersAdapter(getActivity(), entries));
findingLocation.dismiss();
}else {
message = "Sorry! Some records are missing";
String reason = message;
Toast.makeText(view.getContext(), reason, Toast.LENGTH_SHORT).show();
}
}
}
that will work
I am using androidplot to show a graph, the labels get repeated. i searched forums and stackoverflow haven't found any solution.
now i noticed, if arraysize for x-axis or y-axis is less than 10, the array values get duplicated.
The screenshots show the left axis repeating the value 0,1,2. x-axis values are getting repeated. What is your best suggestion on solving this repeating label issue? Any help would be grateful. If you need any further information let me know.
/**
* A simple XYPlot
*/
public class SimpleXYPlotActivity extends Activity {
private XYPlot plot;
String[] domainLabels;
String oldDateStr, newDateStr;
Date newDate;
int totalDays;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.graph_xy_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
Intent intent = getIntent();
Bundle bd = intent.getExtras();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
if (bd != null) {
oldDateStr = (String) bd.get("START_DATE");
newDateStr = (String) bd.get("END_DATE");
plot.setTitle("From: "+oldDateStr+" To: "+newDateStr);
try {
Date date1 = format.parse(oldDateStr);
Date date2 = format.parse(newDateStr);
long diff = date2.getTime() - date1.getTime();
totalDays = Integer.parseInt(String.valueOf(TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS)));
System.out.println ("Days: " + TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS));
} catch (ParseException e) {
e.printStackTrace();
}
}
SimpleDateFormat formatterDateGraph = new SimpleDateFormat("MMM d");
SimpleDateFormat formatterDate = new SimpleDateFormat("yyyy-MM-dd");
try {
newDate = format.parse(newDateStr);
} catch (ParseException e) {
e.printStackTrace();
}
DatabaseHandler db = new DatabaseHandler(this);
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(newDate);
domainLabels= new String[totalDays];
Number[] series1Numbers = new Number[totalDays];
//domain 0 set outside loop for oldDateStr
domainLabels[0]=String.valueOf(formatterDateGraph.format(newDate.getTime()));
List<Orders> reportForDayList = db.getReportByTranType(oldDateStr, oldDateStr,"1");
series1Numbers[0]=reportForDayList.size();
for (int i = 1; i <totalDays ; i++) {
cal.add(Calendar.DAY_OF_YEAR, -1);
domainLabels[i] = String.valueOf(formatterDateGraph.format(cal.getTime()));
//fetch ordercount for that day
reportForDayList = db.getReportByTranType(formatterDate.format(cal.getTime()),formatterDate.format(cal.getTime()),"1");
series1Numbers[i]=reportForDayList.size();
}
series1Numbers = reverseSeries(series1Numbers);
domainLabels = reverseDomain(domainLabels);
//reverseNumber array
// domainLabels = reverseNumber(domainLabels);
// 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, "Sales");
/* 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(Color.RED, Color.GREEN, Color.BLUE, null);
LineAndPointFormatter series2Format = new LineAndPointFormatter(Color.RED, Color.GREEN, Color.BLUE, null);
// 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));*/
// 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));
// add a new series' to the xyplot:
plot.addSeries(series1, series1Format);
// plot.addSeries(series2, series2Format);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).setFormat(new DecimalFormat("#"));
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
#Override
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
int i = Math.round(((Number) obj).floatValue());
return toAppendTo.append(domainLabels[i]);
}
#Override
public Object parseObject(String source, ParsePosition pos) {
return null;
}
});
}
public static Number[] reverseSeries(Number[] a)
{
int l = a.length;
for (int j = 0; j < l / 2; j++)
{
Number temp = a[j];
a[j] = a[l - j - 1];
a[l - j - 1] = temp;
}
return a;
}
public static String[] reverseDomain(String[] a)
{
int l = a.length;
for (int j = 0; j < l / 2; j++)
{
String temp = a[j];
a[j] = a[l - j - 1];
a[l - j - 1] = temp;
}
return a;
}
}
You are creating the domain values by transforming a 6 day range into long values and then subdividing the total range within those values into 10 distinct segments: You can't get 10 day labels from a range of 6 days.
To solve this problem you can either reduce the number of domain segments you are displaying or show more days worth of data.
I want to randomly generate times and numbers.. Here I used hashmap generate some records. Now I can generate the numbers but I cant separate them. I have to separate the values so that I can set those in database..
Here is my code...
public class DateTimePopulation {
private Random rand = new Random();
private Date theDay;
private String callDuration = null;
private String endDay = null;
SimpleDateFormat mytimeFormat = new SimpleDateFormat("HH:mm:ss");
public static void main(String[] args) throws ParseException {
DateTimePopulation d = new DateTimePopulation();
for (int i = 1; i <= 3; i++) {
Map rec = d.getRecord();
for (int j = 0; j < rec.size(); j++) {
Collection c = rec.values();
Iterator itr = c.iterator();
int count=0;
while (itr.hasNext()) {
Object element=itr.next();
System.out.println(element);
}
System.out.println();
}
}
}
private Map getRecord() {
Map<String, Object> rec = new LinkedHashMap<String, Object>();
Date startDate;
try {
startDate = getRandStartDate();
rec.put("StartTime", startDate);
int start = 7200000, end = 0;
int duration = getRandDuration(start, end);
rec.put("Duration", duration);
Date endDate = getRandEndDate(startDate, duration);
rec.put("EndTime", endDate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rec;
}
private Date getRandEndDate(Date startDate, int duration) {
Random r = new Random();
int ranSec = r.nextInt(duration - 0) + 0;
return new Date(startDate.getTime() + ranSec * 1000);
}
private int getRandDuration(int High, int Low) {
Random r = new Random();
return r.nextInt(High - Low) + Low;
}
private Date getRandStartDate() throws ParseException {
Date theDay = new SimpleDateFormat("yyyyMMdd hh:mm:ss")
.parse("20130101 00:00:00");
int High = 60 * 60 * 24 * 30 * 6;
Random r = new Random();
int Low = 10;
int R = r.nextInt(High - Low) + Low;
return new Date(theDay.getTime() + R * 1000);
}
}
Here is the output. I am showing 2 set of it. I have to separate the time, duration etc.
Tue Jan 08 11:01:57 IST 2013
6074479
Fri Jan 18 12:56:24 IST 2013
Firstly, your design is strange to start with - why are you calling getRecord() on an instance, when it doesn't do anything with the fields of the object you're calling it on?
Additionally, when you're iterating over a map, you're actually iterating over the same map 3 times:
for (int j = 0; j < rec.size(); j++) {
Collection c = rec.values();
Iterator itr = c.iterator();
int count=0;
while (itr.hasNext()) {
Object element=itr.next();
System.out.println(element);
}
System.out.println();
}
Your outer loop is pointless here - you're never using j, after all. I would probably iterate over the entries rather than the values, if you really want to - then you can print out the key which goes with each value.
Next, I would encourage you not to use a map for this at all - create a separate type with fields for start time, duration and end time. That will fix things very simply.
Next, if you still want to use a map, stop using the raw types - it'll make your life simpler.
Finally, if you really still want to use a map, you already know the keys, so there's no point in iterating over it:
System.out.println("Start: " + map.get("StartTime");
System.out.println("Duration: " + map.get("Duration");
System.out.println("End: " + map.get("EndTime");
Basically, I strongly suggest that you take a step back and revisit your whole design. You may well find it's better to start from scratch than to change your existing code.
Try to generify this code:
private Map getRecord() {
Map<String, Object> rec = new LinkedHashMap<String, Object>();
Date startDate;
try {
startDate = getRandStartDate();
rec.put("StartTime", startDate);
int start = 7200000, end = 0;
int duration = getRandDuration(start, end);
rec.put("Duration", duration);
Date endDate = getRandEndDate(startDate, duration);
rec.put("EndTime", endDate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rec;
}
Something like that:
private DateInterval getRecord() {
DateInterval interval = null;
try {
Date startDate = getRandStartDate();
int start = 7200000, end = 0;
int duration = getRandDuration(start, end);
Date endDate = getRandEndDate(startDate, duration);
interval = new DateInterval(startDate, endDate, duration);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return interval;
}
See also:
public class DateInterval {
private Date startDate;
private Date endDate;
private int duration;
public DateInterval(Date startDate, Date endDate, int duration) {
this.startDate = startDate;
this.endDate = endDate;
this.duration = duration;
}
public Date getStartDate() {
return startDate;
}
public Date getEndDate() {
return endDate;
}
public int getDuration() {
return duration;
}
}
I mean, you don't need Map for this purpose, use the your own entity. If you need to hold all your entities at Collection, use Map with DB UUIDs as a keys or List.