Hourly data grouped by day, setting location updates data
This commit is contained in:
@@ -4,15 +4,15 @@ import android.app.AlertDialog;
|
||||
import android.app.TabActivity;
|
||||
import android.content.Intent;
|
||||
import android.location.Address;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.ExpandableListView;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import eur.one00kb.minipogodynka.adapters.DetailsAdapter;
|
||||
@@ -21,7 +21,6 @@ import eur.one00kb.minipogodynka.weather.WeatherAPIFetcher;
|
||||
import eur.one00kb.minipogodynka.weather.WeatherAPIParser;
|
||||
import eur.one00kb.minipogodynka.weather.WeatherData;
|
||||
|
||||
// TODO: Searching functionality
|
||||
// TODO: Location history
|
||||
// TODO: Replace Date with Calendar, apparently it's better
|
||||
// TODO: Action icons
|
||||
@@ -34,40 +33,53 @@ public class MainActivity extends TabActivity {
|
||||
|
||||
private PreferenceHolder mPreferenceHolder;
|
||||
private Address mCurrentAddress;
|
||||
private Map<Date, WeatherData> mWeatherData;
|
||||
private Map<Date, List<WeatherData>> mWeatherData;
|
||||
|
||||
private LocationSearchView mLocationSearchView;
|
||||
private ListView mHourlyView;
|
||||
private HourlyAdapter mHourlyAdapter;
|
||||
private DetailsAdapter mDetailsAdapter;
|
||||
private ExpandableListView mHourlyView;
|
||||
|
||||
private AlertDialog mLocationDialog;
|
||||
private AlertDialog.Builder mDetailsDialogBuilder;
|
||||
private AlertDialog mLocationSearchDialog;
|
||||
private AlertDialog mDetailsDialog;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mPreferenceHolder = new PreferenceHolder(this);
|
||||
mHourlyAdapter = new HourlyAdapter(this);
|
||||
mDetailsAdapter = new DetailsAdapter(this);
|
||||
|
||||
mLocationSearchView = (LocationSearchView)
|
||||
getLayoutInflater().inflate(R.layout.dialog_location, null);
|
||||
|
||||
mLocationDialog = new AlertDialog.Builder(this)
|
||||
mLocationSearchDialog = new AlertDialog.Builder(this)
|
||||
.setCancelable(false)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setTitle(R.string.dialog_search_title)
|
||||
.setView(mLocationSearchView).create();
|
||||
.setView(getLayoutInflater().inflate(R.layout.dialog_search, null))
|
||||
.create();
|
||||
|
||||
mDetailsDialogBuilder = new AlertDialog.Builder(this)
|
||||
mDetailsDialog = new AlertDialog.Builder(this)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(android.R.string.ok, null);
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setAdapter(mDetailsAdapter, null)
|
||||
.create();
|
||||
|
||||
mHourlyView = new ListView(this);
|
||||
mHourlyView.setOnItemClickListener((parent, view, position, id) -> {
|
||||
WeatherData data = (WeatherData) mHourlyView.getItemAtPosition(position);
|
||||
mDetailsDialogBuilder
|
||||
.setTitle(String.format("%tR, %<tA", data.date))
|
||||
.setAdapter(new DetailsAdapter(this, data.getMemberInfo()), null)
|
||||
.show();
|
||||
mHourlyView = new ExpandableListView(this);
|
||||
mHourlyView.setAdapter(mHourlyAdapter);
|
||||
|
||||
mHourlyView.setOnChildClickListener((parent, view, groupPosition, childPosition, id) -> {
|
||||
WeatherData data = (WeatherData) mHourlyAdapter.getChild(groupPosition, childPosition);
|
||||
|
||||
mDetailsAdapter.clear();
|
||||
|
||||
for (WeatherData.MemberInfo info : data.getMemberInfo()) {
|
||||
mDetailsAdapter.add(info);
|
||||
}
|
||||
|
||||
mDetailsAdapter.notifyDataSetChanged();
|
||||
mDetailsDialog.setTitle(String.format("%tR, %<tA", data.date));
|
||||
mDetailsDialog.show();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
getTabHost().addTab(getTabHost().newTabSpec("hourly")
|
||||
@@ -88,9 +100,9 @@ public class MainActivity extends TabActivity {
|
||||
int id = item.getItemId();
|
||||
|
||||
if (id == R.id.action_update) {
|
||||
updateApiData();
|
||||
fetchApiData(this::updateInfo);
|
||||
} else if (id == R.id.action_location) {
|
||||
mLocationDialog.show();
|
||||
mLocationSearchDialog.show();
|
||||
} else if (id == R.id.action_settings) {
|
||||
startActivity(new Intent(this, SettingsActivity.class));
|
||||
}
|
||||
@@ -101,25 +113,16 @@ public class MainActivity extends TabActivity {
|
||||
public void setAddress(Address address) {
|
||||
mCurrentAddress = address;
|
||||
setTitle(mCurrentAddress.getAddressLine(0));
|
||||
}
|
||||
|
||||
public void dismissLocationDialog() {
|
||||
mLocationDialog.dismiss();
|
||||
mLocationSearchDialog.dismiss();
|
||||
fetchApiData(this::updateInfo);
|
||||
}
|
||||
|
||||
private void updateInfo() {
|
||||
Date forApiDate = Utilities.getDateOnly();
|
||||
ArrayList<WeatherData> forAdapter = new ArrayList<>();
|
||||
|
||||
for (int i = forApiDate.getHours(); i < 24; ++i) {
|
||||
forApiDate.setHours(i);
|
||||
forAdapter.add(mWeatherData.get(forApiDate));
|
||||
}
|
||||
|
||||
mHourlyView.setAdapter(new HourlyAdapter(this, forAdapter));
|
||||
mHourlyAdapter.setKeysAndData(new ArrayList<>(mWeatherData.keySet()), mWeatherData);
|
||||
mHourlyAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void updateApiData() {
|
||||
private void fetchApiData(Runnable afterCallback) {
|
||||
if (mCurrentAddress == null) {
|
||||
return;
|
||||
}
|
||||
@@ -130,7 +133,7 @@ public class MainActivity extends TabActivity {
|
||||
String apiData = WeatherAPIFetcher.fetch(mCurrentAddress.getLatitude(),
|
||||
mCurrentAddress.getLongitude(), mPreferenceHolder.getProvider());
|
||||
mWeatherData = WeatherAPIParser.parse(apiData, mPreferenceHolder.getProvider());
|
||||
runOnUiThread(this::updateInfo);
|
||||
runOnUiThread(afterCallback);
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import android.widget.Toast;
|
||||
import java.util.Date;
|
||||
|
||||
public class Utilities {
|
||||
public static Date getDateOnly() {
|
||||
public static Date getDayOnly() {
|
||||
Date date = new Date();
|
||||
date.setHours(0);
|
||||
date.setMinutes(0);
|
||||
@@ -15,6 +15,15 @@ public class Utilities {
|
||||
return date;
|
||||
}
|
||||
|
||||
public static Date toDayOnly(Date date) {
|
||||
Date clone = (Date) date.clone();
|
||||
date.setHours(0);
|
||||
date.setMinutes(0);
|
||||
date.setSeconds(0);
|
||||
date.setTime(date.getTime() - (date.getTime() % 1000));
|
||||
return clone;
|
||||
}
|
||||
|
||||
public static void quickToast(Context context, String message) {
|
||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -11,8 +11,8 @@ import eur.one00kb.minipogodynka.R;
|
||||
import eur.one00kb.minipogodynka.weather.WeatherData;
|
||||
|
||||
public class DetailsAdapter extends ArrayAdapter<WeatherData.MemberInfo> {
|
||||
public DetailsAdapter(Context context, WeatherData.MemberInfo[] objects) {
|
||||
super(context, 0, objects);
|
||||
public DetailsAdapter(Context context) {
|
||||
super(context, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,41 +1,108 @@
|
||||
package eur.one00kb.minipogodynka.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Layout;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.BaseExpandableListAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import eur.one00kb.minipogodynka.R;
|
||||
import eur.one00kb.minipogodynka.weather.WeatherData;
|
||||
|
||||
public class HourlyAdapter extends ArrayAdapter<WeatherData> {
|
||||
public HourlyAdapter(Context context, List<WeatherData> objects) {
|
||||
super(context, 0, objects);
|
||||
public class HourlyAdapter extends BaseExpandableListAdapter {
|
||||
private Context mContext;
|
||||
private final List<Date> mKeys;
|
||||
private final Map<Date, List<WeatherData>> mData;
|
||||
|
||||
public HourlyAdapter(Context context) {
|
||||
mContext = context;
|
||||
mKeys = new ArrayList<>();
|
||||
mData = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public void setKeysAndData(List<Date> keys, Map<Date, List<WeatherData>> data) {
|
||||
mKeys.clear();
|
||||
mData.clear();
|
||||
mKeys.addAll(keys);
|
||||
mData.putAll(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
public int getGroupCount() {
|
||||
return mKeys.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildrenCount(int groupPosition) {
|
||||
return mData.get(mKeys.get(groupPosition)).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGroup(int groupPosition) {
|
||||
return mKeys.get(groupPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getChild(int groupPosition, int childPosition) {
|
||||
return mData.get(mKeys.get(groupPosition)).get(childPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getGroupId(int groupPosition) {
|
||||
return groupPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChildId(int groupPosition, int childPosition) {
|
||||
return childPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_hour, parent,
|
||||
false);
|
||||
convertView = LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.item_group, null);
|
||||
}
|
||||
|
||||
WeatherData data = getItem(position);
|
||||
TextView time = convertView.findViewById(R.id.hour_time);
|
||||
TextView temperature = convertView.findViewById(R.id.hour_temp);
|
||||
TextView precipitation = convertView.findViewById(R.id.hour_precp);
|
||||
|
||||
if (data != null) {
|
||||
time.setText(String.format("%tR", data.date));
|
||||
// No one cares about the decimals.
|
||||
temperature.setText(String.format("%d °C", Math.round(data.temperature)));
|
||||
precipitation.setText(String.format("%d %%", Math.round(data.precipitation)));
|
||||
}
|
||||
((TextView) convertView).setText(String.format("%tA, %<td",
|
||||
(Date) getGroup(groupPosition)));
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_hour, null);
|
||||
}
|
||||
|
||||
WeatherData child = (WeatherData) getChild(groupPosition, childPosition);
|
||||
|
||||
((TextView) convertView.findViewById(R.id.hour_time))
|
||||
.setText(String.format("%tR", child.date));
|
||||
((TextView) convertView.findViewById(R.id.hour_temp))
|
||||
.setText(String.format("%.0f °C", child.temperature));
|
||||
((TextView) convertView.findViewById(R.id.hour_precp))
|
||||
.setText(String.format("%.0f %%", child.precipitation));
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildSelectable(int groupPosition, int childPosition) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-7
@@ -1,16 +1,12 @@
|
||||
package eur.one00kb.minipogodynka;
|
||||
package eur.one00kb.minipogodynka.views;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.location.Address;
|
||||
import android.location.Geocoder;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
@@ -24,10 +20,14 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import eur.one00kb.minipogodynka.MainActivity;
|
||||
import eur.one00kb.minipogodynka.R;
|
||||
import eur.one00kb.minipogodynka.adapters.AddressAdapter;
|
||||
|
||||
// TODO: This doesn't need to have a parent. However, for some reason it screams with a bunch of
|
||||
// exceptions when you extend AutoCompleteTextView.
|
||||
// TODO: Make this tabbed, and add coordinates. The dialog neutral button will then be used for
|
||||
// geolocating.
|
||||
|
||||
public class LocationSearchView extends LinearLayout
|
||||
implements TextWatcher, AdapterView.OnItemClickListener {
|
||||
@@ -94,8 +94,6 @@ public class LocationSearchView extends LinearLayout
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
((MainActivity) getContext()).setAddress(mAddressAdapter.getItem(position));
|
||||
((MainActivity) getContext()).dismissLocationDialog();
|
||||
|
||||
AutoCompleteTextView mSearchField = findViewById(R.id.dl_search);
|
||||
mSearchField.setText("");
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package eur.one00kb.minipogodynka.weather;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -7,21 +9,26 @@ import org.json.JSONObject;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import eur.one00kb.minipogodynka.Utilities;
|
||||
|
||||
public class WeatherAPIParser {
|
||||
private static final String TAG = "WeatherAPIParser";
|
||||
private static final DateFormat OM_DATEFORMAT =
|
||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm", Locale.US);
|
||||
private static final DateFormat MET_DATEFORMAT =
|
||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||
|
||||
public static Map<Date, WeatherData> parse(String json, String provider) {
|
||||
public static Map<Date, List<WeatherData>> parse(String json, String provider) {
|
||||
switch (provider) {
|
||||
case "met":
|
||||
return parseMetNo(json);
|
||||
case "mf":
|
||||
return null;
|
||||
case "om":
|
||||
@@ -30,8 +37,8 @@ public class WeatherAPIParser {
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<Date, WeatherData> parseOpenMeteo(String json) {
|
||||
HashMap<Date, WeatherData> hours = new HashMap<>();
|
||||
public static Map<Date, List<WeatherData>> parseOpenMeteo(String json) {
|
||||
Map<Date, List<WeatherData>> weatherDays = new LinkedHashMap<>();
|
||||
|
||||
try {
|
||||
JSONObject root = new JSONObject(json);
|
||||
@@ -47,62 +54,76 @@ public class WeatherAPIParser {
|
||||
JSONArray windDirections = hourly.getJSONArray("wind_direction_10m");
|
||||
JSONArray uvIndexes = hourly.getJSONArray("uv_index");
|
||||
|
||||
for (int i = 0; i < times.length(); ++i) {
|
||||
WeatherData data = new WeatherData();
|
||||
data.date = OM_DATEFORMAT.parse(times.getString(i));
|
||||
data.temperature = temperatures.getDouble(i);
|
||||
data.humidity = humidities.getDouble(i);
|
||||
data.precipitation = precipitations.getDouble(i);
|
||||
data.pressure = pressures.getDouble(i);
|
||||
data.cloudCover = cloudCovers.getDouble(i);
|
||||
data.windSpeed = windSpeeds.getDouble(i);
|
||||
data.windDirection = windDirections.getDouble(i);
|
||||
data.uvIndex = uvIndexes.getDouble(i);
|
||||
Date currentDay = Utilities.toDayOnly(OM_DATEFORMAT.parse(times.getString(0)));
|
||||
List<WeatherData> dayData = new ArrayList<>();
|
||||
|
||||
hours.put(OM_DATEFORMAT.parse(times.getString(i)), data);
|
||||
for (int i = 0; i < times.length(); ++i) {
|
||||
Date day = Utilities.toDayOnly(OM_DATEFORMAT.parse(times.getString(i)));
|
||||
|
||||
if (day.getDay() != currentDay.getDay()) {
|
||||
weatherDays.put(currentDay, dayData);
|
||||
dayData = new ArrayList<>();
|
||||
}
|
||||
|
||||
WeatherData hourData = new WeatherData();
|
||||
hourData.date = OM_DATEFORMAT.parse(times.getString(i));
|
||||
hourData.temperature = temperatures.getDouble(i);
|
||||
hourData.humidity = humidities.getDouble(i);
|
||||
hourData.precipitation = precipitations.getDouble(i);
|
||||
hourData.pressure = pressures.getDouble(i);
|
||||
hourData.cloudCover = cloudCovers.getDouble(i);
|
||||
hourData.windSpeed = windSpeeds.getDouble(i);
|
||||
hourData.windDirection = windDirections.getDouble(i);
|
||||
hourData.uvIndex = uvIndexes.getDouble(i);
|
||||
|
||||
dayData.add(hourData);
|
||||
currentDay = day;
|
||||
}
|
||||
|
||||
weatherDays.put(currentDay, dayData);
|
||||
} catch (JSONException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Error when parsing weather data", e);
|
||||
}
|
||||
|
||||
return hours;
|
||||
Log.d(TAG, weatherDays.toString());
|
||||
return weatherDays;
|
||||
}
|
||||
|
||||
public static Map<Date, WeatherData> parseMetNo(String json) {
|
||||
HashMap<Date, WeatherData> hours = new HashMap<>();
|
||||
|
||||
try {
|
||||
JSONObject root = new JSONObject(json);
|
||||
JSONArray timeseries = root.getJSONObject("properties")
|
||||
.getJSONArray("timeseries");
|
||||
|
||||
for (int i = 0; i < timeseries.length(); ++i) {
|
||||
JSONObject obj = timeseries.getJSONObject(i);
|
||||
JSONObject instant = obj.getJSONObject("data")
|
||||
.getJSONObject("instant").getJSONObject("details");
|
||||
JSONObject next1hr = obj.getJSONObject("data")
|
||||
.getJSONObject("next_1_hours").getJSONObject("details");
|
||||
WeatherData data = new WeatherData();
|
||||
|
||||
data.date = MET_DATEFORMAT.parse(obj.getString("time"));
|
||||
data.temperature = instant.getDouble("air_temperature");
|
||||
data.humidity = instant.getDouble("relative_humidity");
|
||||
// I think this should be correct. If the time is 13, then it's the data for the
|
||||
// next 60 minutes, isn't it?
|
||||
data.precipitation = next1hr.getDouble("precipitation_amount");
|
||||
data.pressure = instant.getDouble("air_pressure_at_sea_level");
|
||||
data.cloudCover = instant.getDouble("cloud_area_fraction");
|
||||
data.windSpeed = instant.getDouble("wind_speed");
|
||||
data.windDirection = instant.getDouble("wind_from_direction");
|
||||
data.uvIndex = instant.getDouble("ultraviolet_index_clear_sky");
|
||||
|
||||
hours.put(MET_DATEFORMAT.parse(obj.getString("time")), data);
|
||||
}
|
||||
} catch (JSONException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return hours;
|
||||
public static void parseMetNo(String json) {
|
||||
// HashMap<Date, WeatherData> hours = new HashMap<>();
|
||||
//
|
||||
// try {
|
||||
// JSONObject root = new JSONObject(json);
|
||||
// JSONArray timeseries = root.getJSONObject("properties")
|
||||
// .getJSONArray("timeseries");
|
||||
//
|
||||
// for (int i = 0; i < timeseries.length(); ++i) {
|
||||
// JSONObject obj = timeseries.getJSONObject(i);
|
||||
// JSONObject instant = obj.getJSONObject("data")
|
||||
// .getJSONObject("instant").getJSONObject("details");
|
||||
// JSONObject next1hr = obj.getJSONObject("data")
|
||||
// .getJSONObject("next_1_hours").getJSONObject("details");
|
||||
// WeatherData data = new WeatherData();
|
||||
//
|
||||
// data.date = MET_DATEFORMAT.parse(obj.getString("time"));
|
||||
// data.temperature = instant.getDouble("air_temperature");
|
||||
// data.humidity = instant.getDouble("relative_humidity");
|
||||
// // I think this should be correct. If the time is 13, then it's the data for the
|
||||
// // next 60 minutes, isn't it?
|
||||
// data.precipitation = next1hr.getDouble("precipitation_amount");
|
||||
// data.pressure = instant.getDouble("air_pressure_at_sea_level");
|
||||
// data.cloudCover = instant.getDouble("cloud_area_fraction");
|
||||
// data.windSpeed = instant.getDouble("wind_speed");
|
||||
// data.windDirection = instant.getDouble("wind_from_direction");
|
||||
// data.uvIndex = instant.getDouble("ultraviolet_index_clear_sky");
|
||||
//
|
||||
// hours.put(MET_DATEFORMAT.parse(obj.getString("time")), data);
|
||||
// }
|
||||
// } catch (JSONException | ParseException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// return hours;
|
||||
}
|
||||
|
||||
public static void parseMeteoFrance() {
|
||||
|
||||
@@ -30,9 +30,9 @@ public class WeatherData {
|
||||
}
|
||||
|
||||
public static class MemberInfo {
|
||||
public String label;
|
||||
public Double value;
|
||||
public String unit;
|
||||
public final String label;
|
||||
public final Double value;
|
||||
public final String unit;
|
||||
|
||||
public MemberInfo(String labela, Double valuea, String unita) {
|
||||
label = labela;
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<eur.one00kb.minipogodynka.LocationSearchView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<eur.one00kb.minipogodynka.views.LocationSearchView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
@@ -9,9 +9,9 @@
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/dl_search"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:completionThreshold="2"
|
||||
android:hint="@string/dialog_search_field"
|
||||
android:dropDownHeight="170dp" />
|
||||
android:dropDownHeight="170dp"
|
||||
android:hint="@string/dialog_search_field" />
|
||||
|
||||
</eur.one00kb.minipogodynka.LocationSearchView>
|
||||
</eur.one00kb.minipogodynka.views.LocationSearchView>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:textSize="24sp">
|
||||
|
||||
</TextView>
|
||||
@@ -2,18 +2,16 @@
|
||||
<resources>
|
||||
<string name="app_name">MiniPogodynka</string>
|
||||
<string name="settings_name">Settings</string>
|
||||
<string name="location_name">Location</string>
|
||||
|
||||
<string name="placeholder">Placeholder</string>
|
||||
|
||||
<string name="dialog_search_title">Set location</string>
|
||||
<string name="dialog_search_field">Search for location</string>
|
||||
<string name="dialog_search_title">Search for location</string>
|
||||
<string name="dialog_search_field">City, street, area…</string>
|
||||
<string name="dialog_search_error">Geocoder unavailable</string>
|
||||
|
||||
<string name="menu_item_update">Update</string>
|
||||
<string name="menu_item_location">Location</string>
|
||||
<string name="menu_item_settings">Settings</string>
|
||||
<string name="menu_item_search">Search</string>
|
||||
|
||||
<string name="preferences_key_provider">weather_provider</string>
|
||||
<string name="preferences_title_provider">Weather provider</string>
|
||||
|
||||
Reference in New Issue
Block a user