kopia lustrzana https://github.com/SP8EBC/MeteoSystem
new activities in station details with wind directiom, temperature and humidity plots
rodzic
5a91b95eb2
commit
920958a7ca
|
@ -13,6 +13,8 @@
|
|||
android:theme="@style/Theme.Pogodacc">
|
||||
<activity android:name=".activity.StationDetailsWindRoseActivity"></activity>
|
||||
<activity android:name=".activity.StationDetailsPlotsWind" />
|
||||
<activity android:name=".activity.StationDetailsPlotsDirection" />
|
||||
<activity android:name=".activity.StationDetailsPlotsTemperature" />
|
||||
<activity android:name=".activity.StationDetailsSummaryActivity" />
|
||||
<activity android:name=".activity.StationDetailsActivity" />
|
||||
<activity android:name=".activity.AllStationsActivity" />
|
||||
|
|
|
@ -4,7 +4,6 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.Image;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.widget.ImageButton;
|
||||
|
@ -14,7 +13,9 @@ import android.widget.TextView;
|
|||
import java.io.InputStream;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActPlotsButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActTemperaturePlotButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActWindDirectionPlotsButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActWindSpeedPlotsButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActSummaryButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActWindRoseButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
|
@ -29,13 +30,30 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
TextView stationSponsorUrl = null;
|
||||
|
||||
ImageButton summaryButton = null;
|
||||
ImageButton plotsButton = null;
|
||||
ImageButton windSpeedPlotsButton = null;
|
||||
ImageButton windDirectionPlotsButton = null;
|
||||
ImageButton temperatureButton = null;
|
||||
ImageButton windRoseButton = null;
|
||||
|
||||
ImageView topBackground = null;
|
||||
|
||||
/**
|
||||
* Click event on Station Summary Button
|
||||
*/
|
||||
StationDetailsActSummaryButtonClickEvent summaryClickEvent = null;
|
||||
StationDetailsActPlotsButtonClickEvent plotsClickEvent = null;
|
||||
|
||||
/**
|
||||
* Click event on Wind Speed Button
|
||||
*/
|
||||
StationDetailsActWindSpeedPlotsButtonClickEvent windSpeedPlotsClickEvent = null;
|
||||
|
||||
StationDetailsActWindDirectionPlotsButtonClickEvent windDirectionPlotsClickEvent = null;
|
||||
|
||||
StationDetailsActTemperaturePlotButtonClickEvent temperaturePlotButtonClickEvent = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
StationDetailsActWindRoseButtonClickEvent windRoseClickEvent = null;
|
||||
|
||||
/**
|
||||
|
@ -113,18 +131,26 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
if (station != null && stationName != null) {
|
||||
|
||||
summaryClickEvent = new StationDetailsActSummaryButtonClickEvent(station, this);
|
||||
plotsClickEvent = new StationDetailsActPlotsButtonClickEvent(station, this);
|
||||
windSpeedPlotsClickEvent = new StationDetailsActWindSpeedPlotsButtonClickEvent(station, this);
|
||||
windDirectionPlotsClickEvent = new StationDetailsActWindDirectionPlotsButtonClickEvent(station, this);
|
||||
temperaturePlotButtonClickEvent = new StationDetailsActTemperaturePlotButtonClickEvent(station, this);
|
||||
windRoseClickEvent = new StationDetailsActWindRoseButtonClickEvent(station, this);
|
||||
|
||||
summaryButton = findViewById(R.id.imageButtonCurrent);
|
||||
summaryButton.setOnClickListener(summaryClickEvent);
|
||||
|
||||
plotsButton = findViewById(R.id.imageButtonPlotsWind);
|
||||
plotsButton.setOnClickListener(plotsClickEvent);
|
||||
windSpeedPlotsButton = findViewById(R.id.imageButtonPlotsWindSpeed);
|
||||
windSpeedPlotsButton.setOnClickListener(windSpeedPlotsClickEvent);
|
||||
|
||||
windDirectionPlotsButton = findViewById(R.id.imageButtonPlotsWindDirection);
|
||||
windDirectionPlotsButton.setOnClickListener(windDirectionPlotsClickEvent);
|
||||
|
||||
windRoseButton = findViewById(R.id.imageButtonWindRose);
|
||||
windRoseButton.setOnClickListener(windRoseClickEvent);
|
||||
|
||||
temperatureButton = findViewById(R.id.imageButtonPlotsTemperature);
|
||||
temperatureButton.setOnClickListener(temperaturePlotButtonClickEvent);
|
||||
|
||||
topBackground = findViewById(R.id.imageViewStationPng);
|
||||
switch (station.getImageAlign()) {
|
||||
case 0:
|
||||
|
|
|
@ -0,0 +1,319 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
import com.github.mikephil.charting.components.XAxis;
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.data.LineData;
|
||||
import com.github.mikephil.charting.data.LineDataSet;
|
||||
import com.github.mikephil.charting.utils.ColorTemplate;
|
||||
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.ZoneId;
|
||||
import org.threeten.bp.ZoneOffset;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.pogodacc.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.pogodacc.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.StationData;
|
||||
|
||||
public class StationDetailsPlotsDirection extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, StationDetailsPlot {
|
||||
|
||||
private LineChart chart = null;
|
||||
private SeekBar seekBarX = null;
|
||||
private TextView textViewTimestamp = null;
|
||||
private TextView textViewSpeed = null;
|
||||
private TextView textViewGusts = null;
|
||||
|
||||
private LastStationDataDao lastStationDataDao;
|
||||
private WeatherStation station;
|
||||
|
||||
private PlotClickEvent plotClickEvent;
|
||||
|
||||
private ArrayList<Entry> valuesWindDirection;
|
||||
|
||||
private class ValueFormatter extends com.github.mikephil.charting.formatter.ValueFormatter {
|
||||
|
||||
@Override
|
||||
public String getFormattedValue(float value) {
|
||||
|
||||
long millis = (long) value;
|
||||
|
||||
// the web service and the plot always stores the entries as UTC. So first convert epoch timestamp to the LocalDateTime
|
||||
LocalDateTime utcDateTime = LocalDateTime.ofEpochSecond(millis / 1000, 0, ZoneOffset.UTC);
|
||||
|
||||
// and then shift to the user timezone for convinient display
|
||||
ZonedDateTime localDateTime = utcDateTime.atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.systemDefault());
|
||||
|
||||
// format only the time to keep X axis clean
|
||||
String dt = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(localDateTime);
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
|
||||
// first and last index to display on plot
|
||||
int first_index = 0, last_index = 0;
|
||||
|
||||
// display only 20% of the set at once
|
||||
int window_size = (int) (valuesWindDirection.size() * 0.2f);
|
||||
|
||||
last_index = (int) ((seekBarX.getProgress() / 100.0f) * valuesWindDirection.size());
|
||||
first_index = last_index - window_size;
|
||||
|
||||
if (first_index < 0) {
|
||||
first_index = 0;
|
||||
last_index = window_size;
|
||||
}
|
||||
|
||||
this.setData(first_index, last_index, false);
|
||||
|
||||
// redraw
|
||||
chart.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerCaptureChanged(boolean hasCapture) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
// download data from web service
|
||||
this.downloadDataFromWebservice();
|
||||
|
||||
Typeface tfLight = Typeface.MONOSPACE;
|
||||
|
||||
setTitle(R.string.wind_direction_plots);
|
||||
|
||||
textViewTimestamp = findViewById(R.id.textViewPlotsWindTimestamp);
|
||||
textViewSpeed = findViewById(R.id.textViewPlotsWindMean);
|
||||
textViewGusts = findViewById(R.id.textViewPlotsWindGusts);
|
||||
seekBarX = findViewById(R.id.seekBarPlotsWind);
|
||||
chart = findViewById(R.id.chartPlotsWind);
|
||||
|
||||
// enable scaling and dragging
|
||||
chart.setDragEnabled(true);
|
||||
chart.setScaleEnabled(true);
|
||||
chart.setDrawGridBackground(false);
|
||||
chart.setHighlightPerDragEnabled(true);
|
||||
|
||||
// set an alternative background color
|
||||
chart.setBackgroundColor(Color.WHITE);
|
||||
chart.setViewPortOffsets(0f, 0f, 0f, 0f);
|
||||
|
||||
// add data
|
||||
seekBarX.setProgress(100);
|
||||
seekBarX.setOnSeekBarChangeListener(this);
|
||||
|
||||
XAxis xAxis = chart.getXAxis();
|
||||
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM_INSIDE);
|
||||
xAxis.setTypeface(tfLight);
|
||||
xAxis.setTextSize(10f);
|
||||
xAxis.setTextColor(Color.WHITE);
|
||||
xAxis.setDrawAxisLine(false);
|
||||
xAxis.setDrawGridLines(true);
|
||||
xAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
xAxis.setCenterAxisLabels(true);
|
||||
xAxis.setGranularity(1f); // one hour
|
||||
xAxis.setValueFormatter(new StationDetailsPlotsDirection.ValueFormatter());
|
||||
|
||||
YAxis leftAxis = chart.getAxisLeft();
|
||||
leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
|
||||
leftAxis.setTypeface(tfLight);
|
||||
leftAxis.setTextColor(ColorTemplate.getHoloBlue());
|
||||
leftAxis.setDrawGridLines(true);
|
||||
leftAxis.setGranularityEnabled(true);
|
||||
leftAxis.setAxisMinimum(0.0f);
|
||||
leftAxis.setAxisMaximum(360.0f);
|
||||
leftAxis.setYOffset(0.0f);
|
||||
leftAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
|
||||
YAxis rightAxis = chart.getAxisRight();
|
||||
rightAxis.setEnabled(false);
|
||||
|
||||
int lastDataIndex = valuesWindDirection.size() - 1;
|
||||
|
||||
// display only the last data (20% of newest data)
|
||||
this.setData((long) (0.8 * (lastDataIndex)), lastDataIndex, false);
|
||||
|
||||
// set bar to maximum value
|
||||
seekBarX.setProgress(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates labels placed at the top of the chart with values at the point selected by an user.
|
||||
* @param date Date & time string in local timezone
|
||||
*/
|
||||
public void updateLabels(String date, Entry entry) {
|
||||
float direction = 0.0f;
|
||||
|
||||
// get a timestamp from the entry
|
||||
long timestamp = (long) entry.getX();
|
||||
|
||||
// look for the windspeed coresponding to that timestamp
|
||||
for (Entry e : valuesWindDirection) {
|
||||
// if this is what we are looking for
|
||||
if (e.getX() == entry.getX()) {
|
||||
direction = e.getY();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (this.textViewSpeed != null && this.textViewTimestamp != null) {
|
||||
this.textViewTimestamp.setText(date);
|
||||
this.textViewSpeed.setText(getString(R.string.wind_direction_short) + String.format(": %d", (int)direction));
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param from
|
||||
* @param to
|
||||
* @param index_or_timestamp if set to false 'to' and 'from' are treated as an index, if they are set
|
||||
* to true this method will use it as epoch timestamps (in seconds)
|
||||
*/
|
||||
public void setData(long from, long to, boolean index_or_timestamp) {
|
||||
|
||||
// if only some part of input set needs to be displayed use this intermediate buffer
|
||||
ArrayList<Entry> narrowed_set, narrowed_set_gusts;
|
||||
|
||||
// data set to be displayed on the plot
|
||||
LineDataSet set_wind_direction;
|
||||
|
||||
|
||||
if (valuesWindDirection.size() > 0) {
|
||||
|
||||
if (from != 0 || to != 0) {
|
||||
|
||||
// if 'from' and 'to' are the index values
|
||||
if (!index_or_timestamp) {
|
||||
// make a sublist
|
||||
narrowed_set = new ArrayList<>(valuesWindDirection.subList((int)from, (int)to));
|
||||
|
||||
}
|
||||
else {
|
||||
// get first and last entry from the set
|
||||
Entry first = valuesWindDirection.get(0);
|
||||
Entry last = valuesWindDirection.get(valuesWindDirection.size() - 1 );
|
||||
|
||||
// check if 'from' and 'to' timestamp epoch covers any data from the input set
|
||||
if ( (long)first.getX() > (to * 1000) ||
|
||||
(long)last.getX() < (from * 1000)) {
|
||||
|
||||
// if there is no data to display exit from an function
|
||||
return;
|
||||
}
|
||||
else {
|
||||
narrowed_set = new ArrayList<>();
|
||||
narrowed_set_gusts = new ArrayList<>();
|
||||
|
||||
// if not copy matching elements to narrowed set
|
||||
valuesWindDirection.forEach((Entry e) -> {
|
||||
if (e.getX() > (from * 1000) &&
|
||||
e.getX() < (to * 1000)) {
|
||||
narrowed_set.add(e);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// and generate the set from it
|
||||
set_wind_direction = new LineDataSet(narrowed_set, "Wind Speed");
|
||||
}
|
||||
else {
|
||||
// use 'values_wind_speed' directly as a whole
|
||||
set_wind_direction = new LineDataSet(valuesWindDirection, "Wind Speed");
|
||||
}
|
||||
|
||||
// create a dataset and give it a type
|
||||
set_wind_direction.setAxisDependency(YAxis.AxisDependency.LEFT);
|
||||
set_wind_direction.setColor(ColorTemplate.getHoloBlue());
|
||||
set_wind_direction.setValueTextColor(ColorTemplate.getHoloBlue());
|
||||
set_wind_direction.setLineWidth(3.5f);
|
||||
set_wind_direction.setDrawCircles(true);
|
||||
set_wind_direction.setDrawValues(true);
|
||||
set_wind_direction.setFillAlpha(65);
|
||||
set_wind_direction.setFillColor(ColorTemplate.getHoloBlue());
|
||||
set_wind_direction.setHighLightColor(Color.rgb(244, 117, 117));
|
||||
set_wind_direction.setDrawCircleHole(false);
|
||||
|
||||
// create a data object with the data sets
|
||||
LineData line_data = new LineData();
|
||||
line_data.addDataSet(set_wind_direction);
|
||||
line_data.setValueTextColor(Color.WHITE);
|
||||
line_data.setValueTextSize(9f);
|
||||
|
||||
// set data
|
||||
chart.setData(line_data);
|
||||
chart.setDoubleTapToZoomEnabled(false);
|
||||
chart.setOnChartValueSelectedListener(plotClickEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the data from the web service and stores it as entries ready to be displayed on the
|
||||
* plot. Web Service gives the data with the epoch timestamp in second resolution, but the plot
|
||||
* shows the data in millisecond resolution
|
||||
*/
|
||||
private void downloadDataFromWebservice() {
|
||||
ListOfStationData data = lastStationDataDao.getLastStationData(station.getSystemName());
|
||||
|
||||
valuesWindDirection = new ArrayList<>();
|
||||
|
||||
if (data instanceof ListOfStationData) {
|
||||
for (StationData d : data.listOfStationData) {
|
||||
valuesWindDirection.add(new Entry(d.epoch * 1000, d.winddir));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public StationDetailsPlotsDirection() {
|
||||
lastStationDataDao = new LastStationDataDao();
|
||||
plotClickEvent = new PlotClickEvent(this);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,329 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
import com.github.mikephil.charting.components.XAxis;
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.data.LineData;
|
||||
import com.github.mikephil.charting.data.LineDataSet;
|
||||
import com.github.mikephil.charting.formatter.IFillFormatter;
|
||||
import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider;
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
import com.github.mikephil.charting.utils.ColorTemplate;
|
||||
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.ZoneId;
|
||||
import org.threeten.bp.ZoneOffset;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.pogodacc.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.pogodacc.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.StationData;
|
||||
|
||||
public class StationDetailsPlotsTemperature extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, StationDetailsPlot {
|
||||
|
||||
WeatherStation station = null;
|
||||
|
||||
private LineChart chart = null;
|
||||
private SeekBar seekBarX = null;
|
||||
private TextView textViewTimestamp = null;
|
||||
private TextView textViewSpeed = null;
|
||||
|
||||
private ArrayList<Entry> valuesTemperature;
|
||||
|
||||
private LastStationDataDao lastStationDataDao;
|
||||
|
||||
PlotClickEvent clickEvent;
|
||||
|
||||
private class ValueFormatter extends com.github.mikephil.charting.formatter.ValueFormatter {
|
||||
|
||||
@Override
|
||||
public String getFormattedValue(float value) {
|
||||
|
||||
long millis = (long) value;
|
||||
|
||||
// the web service and the plot always stores the entries as UTC. So first convert epoch timestamp to the LocalDateTime
|
||||
LocalDateTime utcDateTime = LocalDateTime.ofEpochSecond(millis / 1000, 0, ZoneOffset.UTC);
|
||||
|
||||
// and then shift to the user timezone for convinient display
|
||||
ZonedDateTime localDateTime = utcDateTime.atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.systemDefault());
|
||||
|
||||
// format only the time to keep X axis clean
|
||||
String dt = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(localDateTime);
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public StationDetailsPlotsTemperature() {
|
||||
valuesTemperature = new ArrayList<Entry>();
|
||||
lastStationDataDao = new LastStationDataDao();
|
||||
}
|
||||
|
||||
private void downloadDataFromWebservice() {
|
||||
ListOfStationData data = lastStationDataDao.getLastStationData(station.getSystemName());
|
||||
|
||||
if (data instanceof ListOfStationData) {
|
||||
for (StationData d : data.listOfStationData) {
|
||||
valuesTemperature.add(new Entry(d.epoch * 1000, d.temperature));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates labels placed at the top of the chart with values at the point selected by an user.
|
||||
* @param date Date & time string in local timezone
|
||||
*/
|
||||
public void updateLabels(String date, Entry entry) {
|
||||
float temperature = 0.0f;
|
||||
// get a timestamp from the entry
|
||||
long timestamp = (long) entry.getX();
|
||||
|
||||
// look for the windspeed coresponding to that timestamp
|
||||
for (Entry e : valuesTemperature) {
|
||||
// if this is what we are looking for
|
||||
if (e.getX() == entry.getX()) {
|
||||
temperature = e.getY();
|
||||
}
|
||||
}
|
||||
|
||||
// use wind speed label (on the left) to display the temperature
|
||||
if (this.textViewSpeed != null && this.textViewTimestamp != null) {
|
||||
this.textViewTimestamp.setText(date);
|
||||
this.textViewSpeed.setText(getString(R.string.temperature) + String.format(": %.1f°C", temperature));
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param from
|
||||
* @param to
|
||||
* @param index_or_timestamp if set to false 'to' and 'from' are treated as an index, if they are set
|
||||
* to true this method will use it as epoch timestamps (in seconds)
|
||||
*/
|
||||
public void setData(long from, long to, boolean index_or_timestamp) {
|
||||
|
||||
// if only some part of input set needs to be displayed use this intermediate buffer
|
||||
ArrayList<Entry> narrowed_set, narrowed_set_gusts;
|
||||
|
||||
// data set to be
|
||||
LineDataSet set_temperature;
|
||||
|
||||
|
||||
if (valuesTemperature.size() > 0) {
|
||||
|
||||
if (from != 0 || to != 0) {
|
||||
|
||||
// if 'from' and 'to' are the index values
|
||||
if (!index_or_timestamp) {
|
||||
// make a sublist
|
||||
narrowed_set = new ArrayList<>(valuesTemperature.subList((int)from, (int)to));
|
||||
|
||||
}
|
||||
else {
|
||||
// get first and last entry from the set
|
||||
Entry first = valuesTemperature.get(0);
|
||||
Entry last = valuesTemperature.get(valuesTemperature.size() - 1 );
|
||||
|
||||
// check if 'from' and 'to' timestamp epoch covers any data from the input set
|
||||
if ( (long)first.getX() > (to * 1000) ||
|
||||
(long)last.getX() < (from * 1000)) {
|
||||
|
||||
// if there is no data to display exit from an function
|
||||
return;
|
||||
}
|
||||
else {
|
||||
narrowed_set = new ArrayList<>();
|
||||
narrowed_set_gusts = new ArrayList<>();
|
||||
|
||||
// if not copy matching elements to narrowed set
|
||||
valuesTemperature.forEach((Entry e) -> {
|
||||
if (e.getX() > (from * 1000) &&
|
||||
e.getX() < (to * 1000)) {
|
||||
narrowed_set.add(e);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// and generate the set from it
|
||||
set_temperature = new LineDataSet(narrowed_set, getString(R.string.temperature));
|
||||
}
|
||||
else {
|
||||
// use 'values_wind_speed' directly as a whole
|
||||
set_temperature = new LineDataSet(valuesTemperature, getString(R.string.temperature));
|
||||
}
|
||||
|
||||
// create a dataset and give it a type
|
||||
set_temperature.setMode(LineDataSet.Mode.CUBIC_BEZIER); // filled area instead of only line with points
|
||||
set_temperature.setCubicIntensity(0.2f);
|
||||
set_temperature.setDrawFilled(true);
|
||||
set_temperature.setAxisDependency(YAxis.AxisDependency.LEFT);
|
||||
set_temperature.setColor(ColorTemplate.getHoloBlue());
|
||||
set_temperature.setValueTextColor(ColorTemplate.getHoloBlue());
|
||||
set_temperature.setLineWidth(3.5f);
|
||||
set_temperature.setDrawCircles(false);
|
||||
set_temperature.setDrawValues(true);
|
||||
set_temperature.setFillAlpha(65);
|
||||
set_temperature.setFillColor(ColorTemplate.getHoloBlue());
|
||||
set_temperature.setHighLightColor(Color.rgb(244, 117, 117));
|
||||
set_temperature.setDrawCircleHole(false);
|
||||
set_temperature.setFillFormatter((dataSet, dataProvider) -> 0.0f); // set this to draw an area between
|
||||
// the line and zero axis
|
||||
|
||||
|
||||
// create a data object with the data sets
|
||||
LineData line_data = new LineData();
|
||||
line_data.addDataSet(set_temperature);
|
||||
line_data.setValueTextColor(Color.WHITE);
|
||||
line_data.setValueTextSize(9f);
|
||||
|
||||
// set data
|
||||
chart.setData(line_data);
|
||||
chart.setDoubleTapToZoomEnabled(false);
|
||||
chart.setOnChartValueSelectedListener(clickEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// this activity layout is common for all plots
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
// exit from the function if station object hasn't been added to the intent
|
||||
if (station == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// create click event class
|
||||
clickEvent = new PlotClickEvent(this);
|
||||
|
||||
this.downloadDataFromWebservice();
|
||||
|
||||
// window title
|
||||
setTitle(R.string.wind_direction_plots);
|
||||
|
||||
textViewTimestamp = findViewById(R.id.textViewPlotsWindTimestamp);
|
||||
textViewSpeed = findViewById(R.id.textViewPlotsWindMean);
|
||||
seekBarX = findViewById(R.id.seekBarPlotsWind);
|
||||
chart = findViewById(R.id.chartPlotsWind);
|
||||
|
||||
// enable scaling and dragging
|
||||
chart.setDragEnabled(true);
|
||||
chart.setScaleEnabled(true);
|
||||
chart.setDrawGridBackground(false);
|
||||
chart.setHighlightPerDragEnabled(true);
|
||||
|
||||
// set an alternative background color
|
||||
chart.setBackgroundColor(Color.WHITE);
|
||||
chart.setViewPortOffsets(0f, 0f, 0f, 0f);
|
||||
|
||||
// add data
|
||||
seekBarX.setProgress(100);
|
||||
seekBarX.setOnSeekBarChangeListener(this);
|
||||
|
||||
XAxis xAxis = chart.getXAxis();
|
||||
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM_INSIDE);
|
||||
xAxis.setTypeface(Typeface.MONOSPACE);
|
||||
xAxis.setTextSize(10f);
|
||||
xAxis.setTextColor(Color.WHITE);
|
||||
xAxis.setDrawAxisLine(false);
|
||||
xAxis.setDrawGridLines(true);
|
||||
xAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
xAxis.setCenterAxisLabels(true);
|
||||
xAxis.setGranularity(1f); // one hour
|
||||
xAxis.setValueFormatter(new StationDetailsPlotsTemperature.ValueFormatter());
|
||||
|
||||
YAxis leftAxis = chart.getAxisLeft();
|
||||
leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
|
||||
leftAxis.setTypeface(Typeface.MONOSPACE);
|
||||
leftAxis.setTextColor(ColorTemplate.getHoloBlue());
|
||||
leftAxis.setDrawGridLines(true);
|
||||
leftAxis.setGranularityEnabled(true);
|
||||
leftAxis.setAxisMinimum(-30.0f);
|
||||
leftAxis.setAxisMaximum(40.0f);
|
||||
leftAxis.setYOffset(0.0f);
|
||||
leftAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
|
||||
YAxis rightAxis = chart.getAxisRight();
|
||||
rightAxis.setEnabled(false);
|
||||
|
||||
int lastDataIndex = valuesTemperature.size() - 1;
|
||||
|
||||
// display only the last data (20% of newest data)
|
||||
this.setData((long) (0.8 * (lastDataIndex)), lastDataIndex, false);
|
||||
|
||||
// set bar to maximum value
|
||||
seekBarX.setProgress(100);
|
||||
|
||||
|
||||
//lastDataIndex = valuesWindSpeed.size() - 1;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
|
||||
// first and last index to display on plot
|
||||
int first_index = 0, last_index = 0;
|
||||
|
||||
// display only 20% of the set at once
|
||||
int window_size = (int) (valuesTemperature.size() * 0.2f);
|
||||
|
||||
last_index = (int) ((seekBarX.getProgress() / 100.0f) * valuesTemperature.size());
|
||||
first_index = last_index - window_size;
|
||||
|
||||
if (first_index < 0) {
|
||||
first_index = 0;
|
||||
last_index = window_size;
|
||||
}
|
||||
|
||||
this.setData(first_index, last_index, false);
|
||||
|
||||
// redraw
|
||||
chart.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerCaptureChanged(boolean hasCapture) {
|
||||
|
||||
}
|
||||
}
|
|
@ -27,13 +27,15 @@ import org.threeten.bp.format.FormatStyle;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.WindPlotClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.pogodacc.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.pogodacc.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.StationData;
|
||||
|
||||
public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {
|
||||
public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, StationDetailsPlot {
|
||||
|
||||
private LineChart chart = null;
|
||||
private SeekBar seekBarX = null;
|
||||
|
@ -44,7 +46,7 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
private LastStationDataDao lastStationDataDao;
|
||||
private WeatherStation station;
|
||||
|
||||
private WindPlotClickEvent plotClickEvent;
|
||||
private PlotClickEvent plotClickEvent;
|
||||
|
||||
private ArrayList<Entry> valuesWindSpeed;
|
||||
private ArrayList<Entry> valuesWindGusts;
|
||||
|
@ -76,7 +78,7 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
|
||||
public StationDetailsPlotsWind() {
|
||||
lastStationDataDao = new LastStationDataDao();
|
||||
plotClickEvent = new WindPlotClickEvent(this);
|
||||
plotClickEvent = new PlotClickEvent(this);
|
||||
|
||||
}
|
||||
|
||||
|
@ -85,7 +87,7 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
int lastDataIndex = 0;
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_station_details_plots_wind);
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
|
@ -94,7 +96,7 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
|
||||
Typeface tfLight = Typeface.MONOSPACE;
|
||||
|
||||
setTitle("LineChartTime");
|
||||
setTitle(R.string.wind_speed_plots);
|
||||
|
||||
textViewTimestamp = findViewById(R.id.textViewPlotsWindTimestamp);
|
||||
textViewSpeed = findViewById(R.id.textViewPlotsWindMean);
|
||||
|
@ -197,6 +199,15 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
float mean = 0.0f;
|
||||
float gusts = 0.0f;
|
||||
|
||||
String unit;
|
||||
|
||||
if (AppConfiguration.replaceMsWithKnots) {
|
||||
unit = getString(R.string.knots);
|
||||
}
|
||||
else {
|
||||
unit = getString(R.string.meters_per_second);
|
||||
}
|
||||
|
||||
// get a timestamp from the entry
|
||||
long timestamp = (long) entry.getX();
|
||||
|
||||
|
@ -217,8 +228,8 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
|
||||
if (this.textViewGusts != null && this.textViewSpeed != null && this.textViewTimestamp != null) {
|
||||
this.textViewTimestamp.setText(date);
|
||||
this.textViewSpeed.setText(getString(R.string.mean_value_short) + String.format(" %.1f", mean));
|
||||
this.textViewGusts.setText(getString(R.string.max_value_short) + String.format(" %.1f", gusts));
|
||||
this.textViewSpeed.setText(getString(R.string.mean_value_short) + String.format(": %.1f%s", mean, unit));
|
||||
this.textViewGusts.setText(getString(R.string.wind_gust_short) + String.format(": %.1f%s", gusts, unit));
|
||||
}
|
||||
else {
|
||||
return;
|
||||
|
|
|
@ -46,12 +46,16 @@ public class StationDetailsSummaryActivity extends AppCompatActivity {
|
|||
elems.humidity_val = findViewById(R.id.textViewHumidityValue);
|
||||
elems.message = findViewById(R.id.textViewSummaryMessage);
|
||||
|
||||
// get the summary data for this station
|
||||
summary = summary_dao.getStationSummary(station.getSystemName());
|
||||
|
||||
elems.updateFromSummary(summary, station.getAvailableParameters());
|
||||
|
||||
// create a handler to update station data in background
|
||||
handler = new Handler();
|
||||
updater = new StationDetailsValuesUpdater(elems, handler, station.getSystemName());
|
||||
|
||||
// create a copy of updater class for this tation
|
||||
updater = new StationDetailsValuesUpdater(elems, handler, station.getSystemName(), station);
|
||||
|
||||
if (handler != null && updater != null) {
|
||||
handler.post(updater);
|
||||
|
|
|
@ -59,7 +59,7 @@ public class StationDetailsWindRoseActivity extends AppCompatActivity {
|
|||
elements.updateFromSummary(summary, station.getAvailableParameters());
|
||||
|
||||
handler = new Handler();
|
||||
updater = new StationDetailsValuesUpdater(elements, handler, station.getSystemName());
|
||||
updater = new StationDetailsValuesUpdater(elements, handler, station.getSystemName(), station);
|
||||
|
||||
if (handler != null && updater != null) {
|
||||
// start the handler to update the wind rose activity in background
|
||||
|
|
|
@ -11,16 +11,15 @@ import org.threeten.bp.ZonedDateTime;
|
|||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsPlotsWind;
|
||||
import cc.pogoda.mobile.pogodacc.type.StationDetailsPlot;
|
||||
|
||||
public class WindPlotClickEvent implements OnChartValueSelectedListener {
|
||||
public class PlotClickEvent implements OnChartValueSelectedListener {
|
||||
|
||||
private StationDetailsPlotsWind parent;
|
||||
private StationDetailsPlot parent;
|
||||
|
||||
public WindPlotClickEvent(StationDetailsPlotsWind parent) {
|
||||
public PlotClickEvent(StationDetailsPlot parent) {
|
||||
|
||||
this.parent = parent;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsPlotsTemperature;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActTemperaturePlotButtonClickEvent implements View.OnClickListener {
|
||||
|
||||
WeatherStation station;
|
||||
|
||||
AppCompatActivity p;
|
||||
|
||||
Intent intent;
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
intent = new Intent(p, StationDetailsPlotsTemperature.class);
|
||||
intent.putExtra("station", station);
|
||||
|
||||
p.startActivity(intent);
|
||||
}
|
||||
|
||||
public StationDetailsActTemperaturePlotButtonClickEvent(WeatherStation wx, AppCompatActivity parent) {
|
||||
station = wx;
|
||||
p = parent;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsPlotsDirection;
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsPlotsTemperature;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActWindDirectionPlotsButtonClickEvent implements View.OnClickListener {
|
||||
|
||||
WeatherStation station;
|
||||
|
||||
AppCompatActivity p;
|
||||
|
||||
Intent intent;
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
intent = new Intent(p, StationDetailsPlotsDirection.class);
|
||||
intent.putExtra("station", station);
|
||||
|
||||
p.startActivity(intent);
|
||||
}
|
||||
|
||||
public StationDetailsActWindDirectionPlotsButtonClickEvent(WeatherStation wx, AppCompatActivity parent) {
|
||||
station = wx;
|
||||
p = parent;
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsPlotsWind;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActPlotsButtonClickEvent implements View.OnClickListener {
|
||||
public class StationDetailsActWindSpeedPlotsButtonClickEvent implements View.OnClickListener {
|
||||
|
||||
WeatherStation station;
|
||||
|
||||
|
@ -16,7 +16,7 @@ public class StationDetailsActPlotsButtonClickEvent implements View.OnClickListe
|
|||
|
||||
Intent intent;
|
||||
|
||||
public StationDetailsActPlotsButtonClickEvent(WeatherStation wx, AppCompatActivity parent) {
|
||||
public StationDetailsActWindSpeedPlotsButtonClickEvent(WeatherStation wx, AppCompatActivity parent) {
|
||||
station = wx;
|
||||
|
||||
p = parent;
|
|
@ -5,12 +5,14 @@ import android.os.Handler;
|
|||
import cc.pogoda.mobile.pogodacc.dao.SummaryDao;
|
||||
import cc.pogoda.mobile.pogodacc.type.StationActivityElements;
|
||||
import cc.pogoda.mobile.pogodacc.type.StationSummaryActElements;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.Summary;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class used to update the content of Wind Rose Activity
|
||||
* Class used to update the content of StationDetailsSummaryActivity and
|
||||
* StationDetailsWindRoseActivity
|
||||
*/
|
||||
public class StationDetailsValuesUpdater implements Runnable {
|
||||
|
||||
|
@ -24,10 +26,13 @@ public class StationDetailsValuesUpdater implements Runnable {
|
|||
|
||||
String station_name;
|
||||
|
||||
public StationDetailsValuesUpdater(StationActivityElements elems, Handler h, String s) {
|
||||
WeatherStation station;
|
||||
|
||||
public StationDetailsValuesUpdater(StationActivityElements elems, Handler h, String station_name, WeatherStation station) {
|
||||
elements = elems;
|
||||
handler = h;
|
||||
station_name = s;
|
||||
this.station_name = station_name;
|
||||
this.station = station;
|
||||
|
||||
dao = new SummaryDao();
|
||||
}
|
||||
|
@ -44,7 +49,7 @@ public class StationDetailsValuesUpdater implements Runnable {
|
|||
station_summary = dao.getStationSummary(station_name);
|
||||
|
||||
// null check is done inside this call
|
||||
elements.updateFromSummary(station_summary);
|
||||
elements.updateFromSummary(station_summary, station.getAvailableParameters());
|
||||
|
||||
handler.postDelayed(this, 90000);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package cc.pogoda.mobile.pogodacc.config;
|
||||
|
||||
public class AppConfiguration {
|
||||
|
||||
public static boolean replaceMsWithKnots = false;
|
||||
}
|
|
@ -8,6 +8,9 @@ import cc.pogoda.mobile.pogodacc.web.RestClientConfig;
|
|||
import cc.pogoda.mobile.pogodacc.web.SummaryConsumer;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* This DAO downloads the measurements summary data for wx station given by its name
|
||||
*/
|
||||
public class SummaryDao {
|
||||
|
||||
RestClientConfig restClient;
|
||||
|
@ -20,8 +23,10 @@ public class SummaryDao {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
// create a new instance of factory class. This could be refactored to static invocation
|
||||
restClient = new RestClientConfig();
|
||||
|
||||
// create a new instance of Retrofit with OkHttp client with GSON parser
|
||||
SummaryConsumer consumer = restClient.getWeatherStationClient().create(SummaryConsumer.class);
|
||||
|
||||
try {
|
||||
|
@ -43,15 +48,20 @@ public class SummaryDao {
|
|||
worker.start();
|
||||
|
||||
try {
|
||||
// wait for the web service response
|
||||
worker.join();
|
||||
|
||||
// check if web service returned anything
|
||||
if (response != null) {
|
||||
// if yes get the response body
|
||||
out = response.body();
|
||||
|
||||
if (out != null) {
|
||||
// convert all quality factors from string representation to native format
|
||||
out.temperature_qf_native = QualityFactor.valueOf(out.temperature_qf);
|
||||
out.wind_qf_native = QualityFactor.valueOf(out.wind_qf);
|
||||
out.humidity_qf_native = QualityFactor.valueOf(out.humidity_qf);
|
||||
out.qnh_qf_native = QualityFactor.valueOf(out.qnh_qf);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package cc.pogoda.mobile.pogodacc.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.web.StationDefinition;
|
||||
|
||||
public class AvailableParameters {
|
||||
public class AvailableParameters implements Serializable {
|
||||
|
||||
public boolean windSpeed;
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package cc.pogoda.mobile.pogodacc.type;
|
||||
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
|
||||
public interface StationDetailsPlot {
|
||||
|
||||
void updateLabels(String date, Entry entry);
|
||||
}
|
|
@ -135,7 +135,7 @@ public class StationSummaryActElements implements StationActivityElements {
|
|||
else {
|
||||
temperature_val.setText("---");
|
||||
}
|
||||
|
||||
// TODO
|
||||
if (!s.qnh_qf_native.equals(QualityFactor.NOT_AVALIABLE) && enabledForStation.qnh) {
|
||||
qnh_val.setText(String.format("%d hPa", s.qnh));
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
android:layout_height="611dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButtonPlotsWind"
|
||||
android:id="@+id/imageButtonWindRose"
|
||||
android:layout_width="176dp"
|
||||
android:layout_height="180dp"
|
||||
android:backgroundTint="#56039BE5"
|
||||
|
@ -113,26 +113,25 @@
|
|||
android:scaleType="fitXY"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.068"
|
||||
app:layout_constraintHorizontal_bias="0.931"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.475"
|
||||
app:srcCompat="@drawable/ic_baseline_equalizer_24" />
|
||||
app:layout_constraintVertical_bias="0.037"
|
||||
app:srcCompat="@drawable/ic_wind_rose_compass_svgrepo_com" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewPlots"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="55dp"
|
||||
android:layout_marginTop="141dp"
|
||||
android:layout_marginEnd="59dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:text="@string/wind_speed_plots"
|
||||
android:textAlignment="center"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageButtonPlotsWind"
|
||||
app:layout_constraintEnd_toEndOf="@+id/imageButtonPlotsWind"
|
||||
app:layout_constraintStart_toStartOf="@+id/imageButtonPlotsWind"
|
||||
app:layout_constraintTop_toTopOf="@+id/imageButtonPlotsWind" />
|
||||
android:id="@+id/textViewWindRose"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="57dp"
|
||||
android:layout_marginTop="142dp"
|
||||
android:layout_marginEnd="61dp"
|
||||
android:layout_marginBottom="19dp"
|
||||
android:text="@string/wind_rose"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageButtonWindRose"
|
||||
app:layout_constraintEnd_toEndOf="@+id/imageButtonWindRose"
|
||||
app:layout_constraintStart_toStartOf="@+id/imageButtonWindRose"
|
||||
app:layout_constraintTop_toTopOf="@+id/imageButtonWindRose" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButtonCurrent"
|
||||
|
@ -152,24 +151,6 @@
|
|||
app:layout_constraintVertical_bias="0.037"
|
||||
app:srcCompat="@drawable/ic_baseline_timer_24" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButtonWindRose"
|
||||
android:layout_width="176dp"
|
||||
android:layout_height="180dp"
|
||||
android:backgroundTint="#56039BE5"
|
||||
android:paddingLeft="100px"
|
||||
android:paddingTop="100px"
|
||||
android:paddingRight="100px"
|
||||
android:paddingBottom="100px"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.931"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.037"
|
||||
app:srcCompat="@drawable/ic_wind_rose_compass_svgrepo_com" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewCurrent"
|
||||
android:layout_width="131dp"
|
||||
|
@ -185,19 +166,138 @@
|
|||
app:layout_constraintStart_toStartOf="@+id/imageButtonCurrent"
|
||||
app:layout_constraintTop_toTopOf="@+id/imageButtonCurrent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButtonPlotsTemperature"
|
||||
android:layout_width="176dp"
|
||||
android:layout_height="180dp"
|
||||
android:backgroundTint="#56039BE5"
|
||||
android:paddingLeft="100px"
|
||||
android:paddingTop="100px"
|
||||
android:paddingRight="100px"
|
||||
android:paddingBottom="100px"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.068"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.475"
|
||||
app:srcCompat="@drawable/ic_baseline_equalizer_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewWindRose"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="57dp"
|
||||
android:layout_marginTop="142dp"
|
||||
android:layout_marginEnd="61dp"
|
||||
android:layout_marginBottom="19dp"
|
||||
android:text="@string/wind_rose"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageButtonWindRose"
|
||||
app:layout_constraintEnd_toEndOf="@+id/imageButtonWindRose"
|
||||
app:layout_constraintStart_toStartOf="@+id/imageButtonWindRose"
|
||||
app:layout_constraintTop_toTopOf="@+id/imageButtonWindRose" />
|
||||
android:id="@+id/textViewPlotsTemperature"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="55dp"
|
||||
android:layout_marginTop="141dp"
|
||||
android:layout_marginEnd="59dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:text="@string/temperature_plot"
|
||||
android:textAlignment="center"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageButtonPlotsTemperature"
|
||||
app:layout_constraintEnd_toEndOf="@+id/imageButtonPlotsTemperature"
|
||||
app:layout_constraintStart_toStartOf="@+id/imageButtonPlotsTemperature"
|
||||
app:layout_constraintTop_toTopOf="@+id/imageButtonPlotsTemperature" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButtonPlotsHumidity"
|
||||
android:layout_width="176dp"
|
||||
android:layout_height="180dp"
|
||||
android:backgroundTint="#56039BE5"
|
||||
android:paddingLeft="100px"
|
||||
android:paddingTop="100px"
|
||||
android:paddingRight="100px"
|
||||
android:paddingBottom="100px"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.931"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.475"
|
||||
app:srcCompat="@drawable/ic_baseline_equalizer_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewPlotsHumidity"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="55dp"
|
||||
android:layout_marginTop="141dp"
|
||||
android:layout_marginEnd="59dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:text="@string/humidity_plot"
|
||||
android:textAlignment="center"
|
||||
app:layout_constraintBottom_toBottomOf="@id/imageButtonPlotsHumidity"
|
||||
app:layout_constraintEnd_toEndOf="@id/imageButtonPlotsHumidity"
|
||||
app:layout_constraintStart_toStartOf="@id/imageButtonPlotsHumidity"
|
||||
app:layout_constraintTop_toTopOf="@id/imageButtonPlotsHumidity" />
|
||||
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButtonPlotsWindSpeed"
|
||||
android:layout_width="176dp"
|
||||
android:layout_height="180dp"
|
||||
android:backgroundTint="#56039BE5"
|
||||
android:paddingLeft="100px"
|
||||
android:paddingTop="100px"
|
||||
android:paddingRight="100px"
|
||||
android:paddingBottom="100px"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.068"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.915"
|
||||
app:srcCompat="@drawable/ic_baseline_equalizer_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewPlotsWindSpeed"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="55dp"
|
||||
android:layout_marginTop="141dp"
|
||||
android:layout_marginEnd="59dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:text="@string/wind_speed_plots"
|
||||
android:textAlignment="center"
|
||||
app:layout_constraintBottom_toBottomOf="@id/imageButtonPlotsWindSpeed"
|
||||
app:layout_constraintEnd_toEndOf="@id/imageButtonPlotsWindSpeed"
|
||||
app:layout_constraintStart_toStartOf="@id/imageButtonPlotsWindSpeed"
|
||||
app:layout_constraintTop_toTopOf="@id/imageButtonPlotsWindSpeed" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButtonPlotsWindDirection"
|
||||
android:layout_width="176dp"
|
||||
android:layout_height="180dp"
|
||||
android:backgroundTint="#56039BE5"
|
||||
android:paddingLeft="100px"
|
||||
android:paddingTop="100px"
|
||||
android:paddingRight="100px"
|
||||
android:paddingBottom="100px"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.931"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.915"
|
||||
app:srcCompat="@drawable/ic_baseline_equalizer_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewPlotsWindDirection"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="55dp"
|
||||
android:layout_marginTop="141dp"
|
||||
android:layout_marginEnd="59dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:text="@string/wind_direction_plots"
|
||||
android:textAlignment="center"
|
||||
app:layout_constraintBottom_toBottomOf="@id/imageButtonPlotsWindDirection"
|
||||
app:layout_constraintEnd_toEndOf="@id/imageButtonPlotsWindDirection"
|
||||
app:layout_constraintStart_toStartOf="@id/imageButtonPlotsWindDirection"
|
||||
app:layout_constraintTop_toTopOf="@id/imageButtonPlotsWindDirection" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
android:layout_marginRight="10dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:gravity="right"
|
||||
android:text="testproba123"
|
||||
android:text="@string/click_on_plot"
|
||||
android:textAlignment="center"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
|
@ -36,7 +36,6 @@
|
|||
android:layout_marginRight="10dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:gravity="right"
|
||||
android:text="Avg:"
|
||||
android:textAlignment="textStart"
|
||||
android:textAllCaps="false"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
|
@ -51,7 +50,6 @@
|
|||
android:layout_marginRight="10dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:gravity="right"
|
||||
android:text="Max:"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAllCaps="false"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
@ -66,4 +66,5 @@
|
|||
<string name="temperature_plot">Temperature Plot</string>
|
||||
<string name="humidity_plot">Humidity Plot</string>
|
||||
<string name="station_doesnt_measure">The station doesn\'t measure this parameter</string>
|
||||
<string name="click_on_plot">Click on point on the plot</string>
|
||||
</resources>
|
|
@ -66,4 +66,5 @@
|
|||
<string name="temperature_plot">-</string>
|
||||
<string name="humidity_plot">-</string>
|
||||
<string name="station_doesnt_measure">-</string>
|
||||
<string name="click_on_plot">-</string>
|
||||
</resources>
|
|
@ -66,5 +66,6 @@
|
|||
<string name="temperature_plot">-</string>
|
||||
<string name="humidity_plot">-</string>
|
||||
<string name="station_doesnt_measure">-</string>
|
||||
<string name="click_on_plot">-</string>
|
||||
|
||||
</resources>
|
|
@ -66,4 +66,5 @@
|
|||
<string name="temperature_plot">Temperatura</string>
|
||||
<string name="humidity_plot">Wilgotność</string>
|
||||
<string name="station_doesnt_measure">Stacja nie mierzy tego parametru</string>
|
||||
<string name="click_on_plot">Kliknij na punkt na wykresie</string>
|
||||
</resources>
|
|
@ -66,4 +66,5 @@
|
|||
<string name="temperature_plot">Temperatura</string>
|
||||
<string name="humidity_plot">Wilgotność</string>
|
||||
<string name="station_doesnt_measure">Stacja nie mierzy tego parametru</string>
|
||||
<string name="click_on_plot">Kliknij na punkt na wykresie</string>
|
||||
</resources>
|
|
@ -70,4 +70,7 @@
|
|||
<string name="temperature_plot">Temperature Plot</string>
|
||||
<string name="humidity_plot">Humidity Plot</string>
|
||||
<string name="station_doesnt_measure">The station doesn\'t measure this parameter</string>
|
||||
<string name="meters_per_second" translatable="false">m/s</string>
|
||||
<string name="knots" translatable="false">kts</string>
|
||||
<string name="click_on_plot">Click on point on the plot</string>
|
||||
</resources>
|
Ładowanie…
Reference in New Issue