02.06.2017
mavenCentral()
maven{ url 'https://jitpack.io' }
jcenter{ url 'http://jcenter.bintray.com/' }
compile 'com.github.PhilJay:MPAndroidChart:v3.0.2'
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:background="@color/layoutBackground"
android:id="@+id/frame"
tools:context="de.smarthome_blogger.smarthome.GraphActivity">
<com.github.mikephil.charting.charts.LineChart
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/linechart"
android:visibility="gone"></com.github.mikephil.charting.charts.LineChart>
<include
layout="@layout/loading_animation"
android:visibility="gone"
android:id="@+id/loading_animation"></include>
<include
layout="@layout/empty_item"
android:visibility="gone"
android:id="@+id/empty_item"></include>
</RelativeLayout>
<item android:id="@+id/change_period"
android:title="Zeitraum ändern"
android:orderInCategory="100"
app:showAsAction="always"></item>
private String location, devicetype, post_id, einheit;
private LineChart lineChart;
private ArrayList<GraphDayItem> dayList;
//Für benutzerdefinierten Zeitraum
private final long dayMilliseconds = 60 * 60 * 24 * 1000;
private DateFormat formatter = new SimpleDateFormat("dd.MM.yyyy");
private String date;
private float minVal, maxVal;
public GraphDayItem(String date, float minVal, float maxVal){
this.date = date;
this.minVal = minVal;
this.maxVal = maxVal;
}
/**
* Gibt das Datum zurück
* @return
*/
public String getDate(){
return date;
}
/**
* Gibt den minimalen Wert zurück
* @return
*/
public float getMinVal(){
return minVal;
}
/**
* Gibt den maximalen Wert zurück
* @return
*/
public float getMaxVal(){
return maxVal;
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Bundle bundle = getIntent().getExtras();
setTitle(bundle.getString(MainActivity.EXTRA_TITLE));
location = bundle.getString(MainActivity.EXTRA_LOCATION);
devicetype = bundle.getString(MainActivity.EXTRA_DEVICETYPE);
id = bundle.getString(MainActivity.EXTRA_DEVICE);
//Graph definieren
lineChart = (LineChart) findViewById(R.id.linechart);
lineChart.setDescription(null);
lineChart.setHighlightPerDragEnabled(false);
lineChart.setScaleYEnabled(false);
dayList = new ArrayList<>();
Long now = System.currentTimeMillis();
Long then = now - ((long) (30 * dayMilliseconds)); //30 Tage zuvor
loadGraphData(formatter.format(then), formatter.format(now));
final static String EXTRA_DEVICETYPE = "EXTRA_DEVICETYPE";
final static String EXTRA_START_DATE = "EXTRA_START_DATE";
final static String EXTRA_END_DATE = "EXTRA_END_DATE";
final static String EXTRA_UNIT = "EXTRA_UNIT";
final static String EXTRA_DEVICE = "EXTRA_DEVICE";
final static String EXTRA_ID = "EXTRA_ID";
@Override
public boolean onSupportNavigateUp() {
super.onSupportNavigateUp();
onBackPressed();
getSupportFragmentManager().popBackStack();
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.activity_graph, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item){
int post_id = item.getItemId();
if(post_id == R.id.change_period){
Dialogs.chooseTimePeriodDialog(this, findViewById(R.id.frame), new Dialogs.OnPeriodChosenListener(){
@Override
public void onPeriodChosen(String start, String end){
loadGraphData(start, end);
}
});
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Erstellt einen Dialog, um einen Zeitraum zu bestimmen
* @param activity
* @param view
* @param periodChosenListener
*/
public static void chooseTimePeriodDialog(final Activity activity, final View view, final OnPeriodChosenListener periodChosenListener){
final long dayMilliseconds = 60 * 60 * 24 * 1000;
final DateFormat formatter = new SimpleDateFormat("dd.MM.yyyy");
String[] items = {"Letzte 30 Tage", "Letzte 60 Tage", "Letzte 90 Tage",
"Dieser Monat", "Letzter Monat", "Dieses Jahr", "Letztes Jahr", "Benutzerdefiniert"};
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Zeitraum wählen");
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Long now = System.currentTimeMillis();
Long then;
String vonDatum, bisDatum;
int tag, monat, jahr;
Calendar cal = Calendar.getInstance();
switch(which){
case 0:
then = now - ((long) 30 * dayMilliseconds);
periodChosenListener.onPeriodChosen(formatter.format((then)), formatter.format(now));
break;
case 1:
then = now - ((long) 60 * dayMilliseconds);
periodChosenListener.onPeriodChosen(formatter.format((then)), formatter.format(now));
break;
case 2:
then = now - ((long) 90 * dayMilliseconds);
periodChosenListener.onPeriodChosen(formatter.format((then)), formatter.format(now));
break;
case 3:
tag = 31;
monat = cal.get(Calendar.MONTH);
jahr = cal.get(Calendar.YEAR);
switch (monat){
case Calendar.FEBRUARY:
if((jahr%4)==0){
tag = 29;
}
else tag = 28;
break;
case Calendar.APRIL:
case Calendar.JUNE:
case Calendar.SEPTEMBER:
case Calendar.NOVEMBER:
tag = 30;
break;
}
if(monat == Calendar.DECEMBER){
monat = Calendar.JANUARY;
}
else{
monat++;
}
vonDatum = "01." + monat + "." + jahr;
bisDatum = tag + "." + monat + "." + jahr;
periodChosenListener.onPeriodChosen(vonDatum, bisDatum);
break;
case 4:
tag = 31;
monat = cal.get(Calendar.MONTH);
jahr = cal.get(Calendar.YEAR);
if(monat == Calendar.JANUARY){
monat = Calendar.DECEMBER;
}
else{
monat--;
}
switch (monat){
case Calendar.FEBRUARY:
if((jahr%4)==0){
tag = 29;
}
else tag = 28;
break;
case Calendar.APRIL:
case Calendar.JUNE:
case Calendar.SEPTEMBER:
case Calendar.NOVEMBER:
tag = 30;
break;
}
if(monat == Calendar.DECEMBER){
monat = Calendar.JANUARY;
}
else{
monat++;
}
vonDatum = "01." + monat + "." + jahr;
bisDatum = tag + "." + monat + "." + jahr;
periodChosenListener.onPeriodChosen(vonDatum, bisDatum);
break;
case 5:
vonDatum = "01.01." + cal.get(Calendar.YEAR);
bisDatum = "31.12." + cal.get(Calendar.YEAR);
periodChosenListener.onPeriodChosen(vonDatum, bisDatum);
break;
case 6:
jahr = cal.get(Calendar.YEAR)-1;
vonDatum = "01.01." + jahr;
bisDatum = "31.12." + jahr;
periodChosenListener.onPeriodChosen(vonDatum, bisDatum);
break;
case 7:
Dialogs.chooseCustomTimePeriodDialog(activity, view, periodChosenListener);
break;
}
}
});
builder.setNegativeButton("Abbrechen", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.show();
}
/**
* Erstellt einen Dialog, um einen eigenen Zeitraum zu wählen
* @param activity
* @param v
* @param periodChosenListener
*/
public static void chooseCustomTimePeriodDialog(Activity activity, final View v,
final OnPeriodChosenListener periodChosenListener){
final Map<String, String> periodData = new HashMap<>();
periodData.put("start", null);
periodData.put("end", null);
final Map<String, Long> periodTimestamps = new HashMap<>();
periodTimestamps.put("start", null);
periodTimestamps.put("end", null);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Zeitraum wählen");
final View periodChooserView = activity.getLayoutInflater().inflate(R.layout.period_chooser, null);
final DatePicker datePicker = (DatePicker) periodChooserView.findViewById(R.id.datepicker);
final Button setStartDate = (Button) periodChooserView.findViewById(R.id.startDate);
final Button setEndDate = (Button) periodChooserView.findViewById(R.id.endDate);
builder.setView(periodChooserView);
setStartDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int day = datePicker.getDayOfMonth();
int month = datePicker.getMonth()+1;
int year = datePicker.getYear();
periodData.put("start", ((day<10)?("0"+day):day)+"."+((month<10)?("0"+month):month)+"."+year);
Calendar calendar = new GregorianCalendar(year, month, day);
periodTimestamps.put("start", calendar.getTimeInMillis());
setStartDate.setText(periodData.get("start"));
}
});
setEndDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int day = datePicker.getDayOfMonth();
int month = datePicker.getMonth()+1;
int year = datePicker.getYear();
periodData.put("end", ((day<10)?("0"+day):day)+"."+((month<10)?("0"+month):month)+"."+year);
Calendar calendar = new GregorianCalendar(year, month, day);
periodTimestamps.put("end", calendar.getTimeInMillis());
setStartDate.setText(periodData.get("end"));
}
});
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(periodData.get("start") == null || periodData.get("end") == null){
Dialogs.fehlermeldung("Bitte lege ein Start- und ein Enddatum fest.", v);
}
else{
if(periodTimestamps.get("start") < periodTimestamps.get("end")){
periodChosenListener.onPeriodChosen(periodData.get("start"), periodData.get("end"));
}
else{
Dialogs.fehlermeldung("Das Startdatum muss vor dem Enddatum liegen.", v);
}
}
}
});
builder.setNegativeButton("Abbrechen", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.show();
}
public interface OnPeriodChosenListener{
/**
* Wird aufgerufen, wenn ein Zeitraum ausgewählt wurde
* @param start
* @param end
*/
void onPeriodChosen(String start, String end);
}
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<DatePicker
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/datepicker"></DatePicker>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Startdatum"
style="@style/Base.Widget.AppCompat.Button.Colored"
android:background="@color/colorPrimary"
android:textColor="@color/textColorLight"
android:textAllCaps="false"
android:id="@+id/startDate"
android:layout_weight="1"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Enddatum"
style="@style/Base.Widget.AppCompat.Button.Colored"
android:background="@color/colorPrimary"
android:textColor="@color/textColorLight"
android:textAllCaps="false"
android:id="@+id/endDate"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
/**
* Lädt die Archivdaten des Sensors im angegebenen Bereich vom Server
* @param vonDatum
* @param bisDatum
*/
public void loadGraphData(String vonDatum, String bisDatum){
lineChart.setVisibility(View.GONE);
findViewById(R.id.empty_item).setVisibility(View.GONE);
findViewById(R.id.loading_animation).setVisibility(View.VISIBLE);
final Map<String, String> requestData = new HashMap<>();
requestData.put("action", "getgraphdata");
requestData.put("room", "location");
requestData.put("type", devicetype);
requestData.put("id", post_id);
requestData.put("von", vonDatum);
requestData.put("bis", bisDatum);
requestData.put("username", SaveData.getUsername(getApplicationContext()));
requestData.put("password", SaveData.getPassword(getApplicationContext()));
HTTPRequest.sendRequest(getApplicationContext(), requestData, SaveData.getServerIp(getApplicationContext()), new HTTPRequest.HTTPRequestCallback() {
@Override
public void onRequestResult(String result) {
findViewById(R.id.loading_animation).setVisibility(View.GONE);
switch(result){
default:
try{
JSONObject jsonObject = new JSONObject(result);
JSONArray values = jsonObject.getJSONArray("values");
einheit = jsonObject.getString("einheit");
dayList.clear();
for(int i = 0; i < values.length(); i++){
JSONObject o = values.getJSONObject(i);
dayList.add(new GraphDayItem(o.getString("date"), BigDecimal.valueOf(o.getDouble("min")).floatValue(),
BigDecimal.valueOf(o.getDouble("max")).floatValue()));
}
fillLineChart();
if(dayList.isEmpty()){
lineChart.setVisibility(View.GONE);
findViewById(R.id.empty_item).setVisibility(View.VISIBLE);
((ImageView) findViewById(R.id.empty_icon)).setImageResource(Icons.getDrawerIcon("overview"));
((TextView) findViewById(R.id.empty_title)).setText("Keine Daten");
((TextView) findViewById(R.id.empty_info)).setText("Für den ausgewählten Zeitraum sind keine Daten vorhanden.");
}
}
catch(JSONException e){
e.printStackTrace();
onError("");
}
break;
}
}
@Override
public void onError(String msg) {
lineChart.setVisibility(View.GONE);
findViewById(R.id.empty_item).setVisibility(View.VISIBLE);
((ImageView) findViewById(R.id.empty_icon)).setImageResource(Icons.getDrawerIcon("overview"));
((TextView) findViewById(R.id.empty_title)).setText("Keine Daten");
((TextView) findViewById(R.id.empty_info)).setText("Die Daten konnten nicht geladen werden");
}
});
}
/**
* Füllt den LineChart mit Werten
*/
public void fillLineChart(){
if(dayList.isEmpty()){
return;
}
ArrayList<Entry> minVals = new ArrayList<>();
ArrayList<Entry> maxVals = new ArrayList<>();
final ArrayList<String> dates = new ArrayList<>();
for(int i = 0; i < dayList.size(); i++){
GraphDayItem item = dayList.get(i);
minVals.add(new Entry(i, (float) item.getMinVal()));
maxVals.add(new Entry(i, (float) item.getMaxVal()));
dates.add(item.getDate());
}
//Einstellungen des Graphen
final LineDataSet minLine = new LineDataSet(minVals, "Minumum");
minLine.setMode(LineDataSet.Mode.CUBIC_BEZIER);
minLine.setCubicIntensity(0.2f);
minLine.setAxisDependency(YAxis.AxisDependency.LEFT);
minLine.setColor(getResources().getColor(R.color.colorPrimary));
minLine.setCircleSize(4.5f);
minLine.setCircleColor(getResources().getColor(R.color.colorPrimary));
minLine.setDrawCircles(true);
minLine.setDrawValues(false);
final LineDataSet maxLine = new LineDataSet(maxVals, "Maximum");
maxLine.setMode(LineDataSet.Mode.CUBIC_BEZIER);
maxLine.setCubicIntensity(0.2f);
maxLine.setAxisDependency(YAxis.AxisDependency.LEFT);
maxLine.setColor(getResources().getColor(R.color.red));
maxLine.setCircleSize(4.5f);
maxLine.setCircleColor(getResources().getColor(R.color.red));
maxLine.setDrawCircles(true);
maxLine.setDrawValues(false);
ArrayList<ILineDataSet> dataSets = new ArrayList<>();
dataSets.add(minLine);
dataSets.add(maxLine);
Legend legend = lineChart.getLegend();
legend.setTextSize(20);
LineData lineData = new LineData(dataSets);
lineChart.animateY(500);
lineChart.setData(lineData);
XAxis xAxis = lineChart.getXAxis();
xAxis.setGranularity(1f);
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
try{
return dates.get((int) value);
}
catch(Exception e){
e.printStackTrace();
return String.valueOf(value);
}
}
});
lineChart.invalidate();
lineChart.setVisibility(View.VISIBLE);
lineChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, Highlight h) {
int index = minLine.getEntryIndex(e);
if(index == -1){
index = maxLine.getEntryIndex(e);
}
if(index == -1){
return;
}
//ValueCourseActivity starten
/*Intent intent = new Intent(GraphActivity.this, ValueCourseActivity.class);
intent.putExtra(MainActivity.EXTRA_START_DATE, dayList.get(index).getDate());
intent.putExtra(MainActivity.EXTRA_DEVICETYPE, devicetype);
intent.putExtra(MainActivity.EXTRA_ID, post_id);
intent.putExtra(MainActivity.EXTRA_LOCATION, location);
intent.putExtra(MainActivity.EXTRA_UNIT, einheit);
startActivity(intent);*/
}
@Override
public void onNothingSelected() {
}
});
}
//GraphActivity aufrufen
Intent intent = new Intent(activity, GraphActivity.class);
intent.putExtra(MainActivity.EXTRA_TITLE, item.getName());
intent.putExtra(MainActivity.EXTRA_LOCATION, location);
intent.putExtra(MainActivity.EXTRA_DEVICETYPE, item.getDeviceType());
intent.putExtra(MainActivity.EXTRA_DEVICE, item.getId());
activity.startActivity(intent);
Dieser Beitrag hat dir gefallen?
Dann abonniere doch unseren Newsletter!