Completed 1, 2, 3 tasks
This commit is contained in:
parent
df7c5e6e3f
commit
f29fe8ad71
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
|
||||
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@ -25,6 +25,10 @@ android {
|
||||
)
|
||||
}
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding = true;
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
@ -41,4 +45,6 @@ dependencies {
|
||||
androidTestImplementation(libs.ext.junit)
|
||||
androidTestImplementation(libs.espresso.core)
|
||||
implementation("com.android.volley:volley:1.2.1")
|
||||
implementation("com.github.bumptech.glide:glide:4.15.1")
|
||||
annotationProcessor("com.github.bumptech.glide:compiler:4.15.1")
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
@ -14,9 +15,6 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.AirQuality"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".AQActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".DetailsActivity"
|
||||
android:exported="false" />
|
||||
|
||||
@ -1,191 +0,0 @@
|
||||
package com.example.airquality;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.JsonObjectRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AQActivity extends AppCompatActivity {
|
||||
private static final Map<String, double[]> cityCoordinates = new HashMap<>();
|
||||
static {
|
||||
cityCoordinates.put("Subotica", new double[]{46.1, 19.6667});
|
||||
cityCoordinates.put("Novi Sad", new double[]{45.2517, 19.8369});
|
||||
cityCoordinates.put("Beograd", new double[]{44.804, 20.4651});
|
||||
cityCoordinates.put("San Francisko", new double[]{37.7749, -122.4194});
|
||||
cityCoordinates.put("Sidnej", new double[]{-33.8679, 151.2073});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_aqactivity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
|
||||
// Using toolbar as ActionBar
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// Display application icon in the toolbar
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
getSupportActionBar().setLogo(R.drawable.weather_clear_symbolic);
|
||||
getSupportActionBar().setDisplayUseLogoEnabled(true);
|
||||
}
|
||||
|
||||
loadAQ();
|
||||
}
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
loadAQ();
|
||||
}
|
||||
|
||||
public boolean onCreateOptionsMenu(android.view.Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
|
||||
inflater.inflate(R.menu.menu_main, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(android.view.MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_aq:
|
||||
Intent intentAQ = new Intent(this, AQActivity.class);
|
||||
startActivity(intentAQ);
|
||||
return true;
|
||||
case R.id.menu_settings:
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
private String getAQIDescription(int aqi) {
|
||||
switch (aqi) {
|
||||
case 1: return "Good";
|
||||
case 2: return "Fair";
|
||||
case 3: return "Moderate";
|
||||
case 4: return "Poor";
|
||||
case 5: return "Very Poor";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
public void loadAQ(){
|
||||
String city = PreferencesManager.getCity(this);
|
||||
double[] coords = cityCoordinates.get(city);
|
||||
if (coords == null) {
|
||||
Toast.makeText(this, "Unknown city: " + city, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
String apiKey = getString(R.string.weather_api_key);
|
||||
String url = String.format(
|
||||
"https://api.openweathermap.org/data/2.5/air_pollution?lat=%.6f&lon=%.6f&appid=%s",
|
||||
coords[0], coords[1], apiKey
|
||||
);
|
||||
|
||||
RequestQueue queue = Volley.newRequestQueue(this);
|
||||
JsonObjectRequest request = new JsonObjectRequest(
|
||||
Request.Method.GET,
|
||||
url,
|
||||
null,
|
||||
new Response.Listener<JSONObject>() {
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
try {
|
||||
// Get JSON fields
|
||||
JSONObject listItem = response.getJSONArray("list").getJSONObject(0);
|
||||
int aqi = listItem.getJSONObject("main").getInt("aqi");
|
||||
|
||||
View rootLayout = findViewById(R.id.main);
|
||||
|
||||
int colorResId;
|
||||
switch (aqi) {
|
||||
case 1:
|
||||
colorResId = R.color.aqi_good;
|
||||
break;
|
||||
case 2:
|
||||
colorResId = R.color.aqi_fair;
|
||||
break;
|
||||
case 3:
|
||||
colorResId = R.color.aqi_moderate;
|
||||
break;
|
||||
case 4:
|
||||
colorResId = R.color.aqi_poor;
|
||||
break;
|
||||
case 5:
|
||||
colorResId = R.color.aqi_very_poor;
|
||||
break;
|
||||
default:
|
||||
colorResId = android.R.color.background_light;
|
||||
}
|
||||
|
||||
rootLayout.setBackgroundColor(getResources().getColor(colorResId));
|
||||
|
||||
JSONObject components = listItem.getJSONObject("components");
|
||||
double pm25 = components.getDouble("pm2_5");
|
||||
double pm10 = components.getDouble("pm10");
|
||||
double o3 = components.getDouble("o3");
|
||||
double co = components.getDouble("co");
|
||||
double no2 = components.getDouble("no2");
|
||||
|
||||
|
||||
TextView tvCity = findViewById(R.id.tvCity);
|
||||
TextView tvAQ = findViewById(R.id.tvAQ);
|
||||
TextView tvComponents = findViewById(R.id.tvComponents);
|
||||
|
||||
|
||||
String city = PreferencesManager.getCity(AQActivity.this);
|
||||
|
||||
|
||||
tvCity.setText("City: " + city);
|
||||
tvAQ.setText("AQI Index: " + aqi + " (" + getAQIDescription(aqi) + ")");
|
||||
tvComponents.setText(
|
||||
String.format("PM2.5: %.2f µg/m³\nPM10: %.2f µg/m³\nO₃: %.2f ppb\nCO: %.2f ppm\nNO₂: %.2f ppb",
|
||||
pm25, pm10, o3, co, no2)
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(AQActivity.this, "Failed to parse air data", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
Toast.makeText(AQActivity.this, "Failed to load air pollution data", Toast.LENGTH_SHORT).show();
|
||||
error.printStackTrace();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
queue.add(request);
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
package com.example.airquality;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
@ -8,13 +11,106 @@ import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
public class DetailsActivity extends AppCompatActivity {
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.example.airquality.api.ForecastAPIRequest;
|
||||
import com.example.airquality.databinding.ActivityDetailsBinding;
|
||||
import com.example.airquality.types.City;
|
||||
import com.example.airquality.types.FormattedTemp;
|
||||
import com.example.airquality.types.Weather3h;
|
||||
import com.example.airquality.utils.PreferencesManager;
|
||||
import com.example.airquality.utils.ToolbarCompatActivity;
|
||||
import com.example.airquality.utils.Weather3hAdapter;
|
||||
import com.example.airquality.utils.Weather3hParser;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class DetailsActivity extends ToolbarCompatActivity {
|
||||
|
||||
private ActivityDetailsBinding binding;
|
||||
private Weather3h weather3h;
|
||||
private City city;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_details);
|
||||
|
||||
binding = ActivityDetailsBinding.inflate(getLayoutInflater());
|
||||
View view = binding.getRoot();
|
||||
setContentView(view);
|
||||
|
||||
Intent intent = getIntent();
|
||||
weather3h = (Weather3h) intent.getSerializableExtra("WEATHER_3H");
|
||||
city = (City) intent.getSerializableExtra("CITY");
|
||||
|
||||
initToolbar();
|
||||
setToolbarTitle(weather3h.getDateTime());
|
||||
updateData();
|
||||
}
|
||||
|
||||
protected void updateData() {
|
||||
FormattedTemp formattedTemp = weather3h.formattedTemp(this);
|
||||
|
||||
if(checkInternet())
|
||||
{
|
||||
Glide.with(this)
|
||||
.load(weather3h.getIconUrl())
|
||||
.into(binding.icon);
|
||||
|
||||
binding.iconCode.setText("");
|
||||
}
|
||||
else
|
||||
{
|
||||
binding.icon.setImageDrawable(null);
|
||||
binding.iconCode.setText(weather3h.getIconCode());
|
||||
}
|
||||
|
||||
binding.cityText.setText(city.name);
|
||||
binding.datetimeText.setText(weather3h.getDateTime());
|
||||
binding.tempWeatherText.setText(formattedTemp.tempText + " | " + weather3h.getDescription());
|
||||
binding.tempText.setText(formattedTemp.tempMinText + " ~ " + formattedTemp.tempMaxText);
|
||||
binding.pressureText.setText(weather3h.getPressure() + " hPa");
|
||||
binding.humidityText.setText(weather3h.getHumidity() + "%");
|
||||
binding.windSpeedText.setText(weather3h.getWindSpeed() + " m/s");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRefreshOptionToolbar() {
|
||||
String units = PreferencesManager.getUnits(this);
|
||||
RequestQueue queue = Volley.newRequestQueue(this);
|
||||
|
||||
ForecastAPIRequest forecastAPI = new ForecastAPIRequest(this, city, units) {
|
||||
@Override
|
||||
public void onSuccess(Weather3h[] weatherList) {
|
||||
boolean isFound = false;
|
||||
for (Weather3h w : weatherList) {
|
||||
if (w.getDateTime().equals(weather3h.getDateTime())) {
|
||||
// Update to new data
|
||||
weather3h = w;
|
||||
isFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isFound) {
|
||||
Toast.makeText(DetailsActivity.this, "Data was updated!", Toast.LENGTH_SHORT).show();
|
||||
updateData();
|
||||
}
|
||||
else {
|
||||
Toast.makeText(DetailsActivity.this, "This time is deprecated", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError error) {
|
||||
Toast.makeText(DetailsActivity.this, "Failed to load weather data", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
|
||||
queue.add(forecastAPI.getRequest());
|
||||
}
|
||||
}
|
||||
@ -2,20 +2,16 @@ package com.example.airquality;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.MenuInflater;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
@ -23,20 +19,25 @@ import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.JsonObjectRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import com.example.airquality.api.ForecastAPIRequest;
|
||||
import com.example.airquality.types.City;
|
||||
import com.example.airquality.types.Weather3h;
|
||||
import com.example.airquality.utils.PreferencesManager;
|
||||
import com.example.airquality.utils.ToolbarCompatActivity;
|
||||
import com.example.airquality.utils.Weather3hAdapter;
|
||||
import com.example.airquality.utils.Weather3hParser;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
public class MainActivity extends ToolbarCompatActivity {
|
||||
List<Weather3h> prognoza;
|
||||
|
||||
private ListView listView;
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
private static final Map<String, double[]> cityCoordinates = new HashMap<>();
|
||||
static {
|
||||
@ -54,81 +55,10 @@ public class MainActivity extends AppCompatActivity {
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
listView=findViewById(R.id.listView);
|
||||
recyclerView=findViewById(R.id.weatherList);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
|
||||
// Assigning ID of the toolbar to a variable
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
|
||||
// Using toolbar as ActionBar
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// Display application icon in the toolbar
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
getSupportActionBar().setLogo(R.drawable.weather_clear_symbolic);
|
||||
getSupportActionBar().setDisplayUseLogoEnabled(true);
|
||||
}
|
||||
|
||||
loadForecast();
|
||||
}
|
||||
|
||||
// private void loadForecast() {
|
||||
// String city = PreferencesManager.getCity(this);
|
||||
// int days = PreferencesManager.getDays(this);
|
||||
// String units = PreferencesManager.getUnits(this);
|
||||
//
|
||||
// Log.d("SETTINGS", "City: " + city + ", Days: " + days + ", Units: " + units);
|
||||
//
|
||||
// try {
|
||||
// // Učitavanje lokalnog JSON fajla
|
||||
// InputStream is = getAssets().open("forecast_sample_40.json");
|
||||
// int size = is.available();
|
||||
// byte[] buffer = new byte[size];
|
||||
// is.read(buffer);
|
||||
// is.close();
|
||||
//
|
||||
// String jsonString = new String(buffer, "UTF-8");
|
||||
// JSONObject jsonObject = new JSONObject(jsonString);
|
||||
//
|
||||
// // Računamo maksimalan broj vremenskih tačaka
|
||||
// int maxPoints = days * 8; // jer ima 8 tačaka dnevno na svakih 3h
|
||||
//
|
||||
// // Parsiramo podatke
|
||||
// List<Weather3h> prognoza = Weather3hParser.parse(jsonObject, maxPoints);
|
||||
//
|
||||
// // Povezujemo adapter sa ListView-om
|
||||
// Weather3hAdapter adapter = new Weather3hAdapter(this, prognoza);
|
||||
// ListView listView = findViewById(R.id.listView);
|
||||
// listView.setAdapter(adapter);
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
public boolean onCreateOptionsMenu(android.view.Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
|
||||
inflater.inflate(R.menu.menu_main, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(android.view.MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_aq:
|
||||
Intent intentAQ = new Intent(this, AQActivity.class);
|
||||
startActivity(intentAQ);
|
||||
return true;
|
||||
case R.id.menu_settings:
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
initToolbar();
|
||||
}
|
||||
|
||||
protected void onResume() {
|
||||
@ -136,59 +66,47 @@ public class MainActivity extends AppCompatActivity {
|
||||
loadForecast();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onRefreshOptionToolbar() {
|
||||
loadForecast(true);
|
||||
}
|
||||
|
||||
private void loadForecast() {
|
||||
String city = PreferencesManager.getCity(this);
|
||||
loadForecast(false);
|
||||
}
|
||||
private void loadForecast(boolean isUpdated) {
|
||||
City city = PreferencesManager.getCity(this);
|
||||
int days = PreferencesManager.getDays(this);
|
||||
String units = PreferencesManager.getUnits(this);
|
||||
|
||||
double[] coords = cityCoordinates.get(city);
|
||||
if (coords == null) {
|
||||
Toast.makeText(this, "Unknown city: " + city, Toast.LENGTH_SHORT).show();
|
||||
setToolbarTitle(city.name);
|
||||
|
||||
if (city == null) {
|
||||
Toast.makeText(this, "Unknown city: " + city.name, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
String apiKey = getString(R.string.weather_api_key);
|
||||
String url = String.format(
|
||||
"https://api.openweathermap.org/data/2.5/forecast?lat=%f&lon=%f&units=%s&appid=%s",
|
||||
coords[0], coords[1], units, apiKey
|
||||
);
|
||||
|
||||
RequestQueue queue = Volley.newRequestQueue(this);
|
||||
|
||||
JsonObjectRequest request = new JsonObjectRequest(
|
||||
Request.Method.GET,
|
||||
url,
|
||||
null,
|
||||
new Response.Listener<JSONObject>() {
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
prognoza = Weather3hParser.parse(response, days);;
|
||||
Weather3hAdapter adapter = new Weather3hAdapter(MainActivity.this, prognoza);
|
||||
ListView listView = findViewById(R.id.listView);
|
||||
listView.setAdapter(adapter);
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
error.printStackTrace();
|
||||
Toast.makeText(MainActivity.this, "Failed to load weather data", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
);
|
||||
ForecastAPIRequest forecastAPI = new ForecastAPIRequest(this, city, units) {
|
||||
@Override
|
||||
public void onSuccess(Weather3h[] weatherList) {
|
||||
Weather3h[] arr = Arrays.copyOfRange(weatherList, 0, days);
|
||||
prognoza = Arrays.asList(arr);
|
||||
|
||||
queue.add(request);
|
||||
Weather3hAdapter adapter = new Weather3hAdapter(MainActivity.this, prognoza, city);
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
if(isUpdated)
|
||||
Toast.makeText(MainActivity.this, "List Updated!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError error) {
|
||||
Toast.makeText(MainActivity.this, "Failed to load weather data", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
|
||||
queue.add(forecastAPI.getRequest());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -17,10 +17,11 @@ import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity {
|
||||
import com.example.airquality.utils.BaseCompatActivity;
|
||||
|
||||
public class SettingsActivity extends BaseCompatActivity {
|
||||
Spinner spinnerCity;
|
||||
RadioGroup radioGroupDays, radioGroupUnits;
|
||||
CheckBox checkBoxRemember;
|
||||
Button buttonSave;
|
||||
|
||||
String[] cities = {"Subotica", "Novi Sad", "Beograd", "San Francisko", "Sidnej"};
|
||||
@ -33,7 +34,6 @@ public class SettingsActivity extends AppCompatActivity {
|
||||
spinnerCity = findViewById(R.id.spinnerCity);
|
||||
radioGroupDays = findViewById(R.id.radioGroupDays);
|
||||
radioGroupUnits = findViewById(R.id.radioGroupUnits);
|
||||
checkBoxRemember = findViewById(R.id.checkBoxRemember);
|
||||
buttonSave = findViewById(R.id.buttonSave);
|
||||
|
||||
// Podesi spinner
|
||||
@ -59,22 +59,13 @@ public class SettingsActivity extends AppCompatActivity {
|
||||
units = "imperial";
|
||||
}
|
||||
|
||||
boolean remember = checkBoxRemember.isChecked();
|
||||
SharedPreferences prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString("city", selectedCity);
|
||||
editor.putInt("days", days);
|
||||
editor.putString("units", units);
|
||||
editor.apply();
|
||||
|
||||
if (remember) {
|
||||
SharedPreferences prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString("city", selectedCity);
|
||||
editor.putInt("days", days);
|
||||
editor.putString("units", units);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra("city", selectedCity);
|
||||
resultIntent.putExtra("days", days);
|
||||
resultIntent.putExtra("units", units);
|
||||
setResult(RESULT_OK, resultIntent);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
package com.example.airquality;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Weather3hAdapter extends BaseAdapter {
|
||||
private Context context;
|
||||
private List<Weather3h> weatherList;
|
||||
private LayoutInflater inflater;
|
||||
|
||||
public Weather3hAdapter(Context context, List<Weather3h> weatherList) {
|
||||
this.context = context;
|
||||
this.weatherList = weatherList;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return weatherList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return weatherList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View rowView = inflater.inflate(R.layout.item_weather3h, parent, false);
|
||||
|
||||
TextView txtDate = rowView.findViewById(R.id.txtDate);
|
||||
TextView txtTemp = rowView.findViewById(R.id.txtTemp);
|
||||
TextView txtDesc = rowView.findViewById(R.id.txtDesc);
|
||||
|
||||
Weather3h item = weatherList.get(position);
|
||||
|
||||
txtDate.setText(item.getDateTime());
|
||||
txtTemp.setText(String.format("%.1f°C", item.getTemp()));
|
||||
txtDesc.setText(item.getDescription());
|
||||
|
||||
return rowView;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.example.airquality.api;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.JsonObjectRequest;
|
||||
import com.example.airquality.types.City;
|
||||
import com.example.airquality.types.Weather3h;
|
||||
import com.example.airquality.utils.Weather3hParser;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ForecastAPIRequest extends JsonAPIRequest {
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
public ForecastAPIRequest(Context context, City city, String units) {
|
||||
super(context);
|
||||
this.url = String.format(
|
||||
"https://api.openweathermap.org/data/2.5/forecast?lat=%f&lon=%f&units=%s&appid=%s",
|
||||
city.latitude, city.longitude, units, getKey()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObjectRequest getRequest() {
|
||||
return new JsonObjectRequest(
|
||||
Request.Method.GET,
|
||||
url,
|
||||
null,
|
||||
new Response.Listener<JSONObject>() {
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
onSuccess(Weather3hParser.parse(response));
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
error.printStackTrace();
|
||||
onError(error);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void onSuccess(Weather3h[] weatherList) { }
|
||||
public void onError(VolleyError error) { }
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.example.airquality.api;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.JsonObjectRequest;
|
||||
import com.example.airquality.MainActivity;
|
||||
import com.example.airquality.R;
|
||||
import com.example.airquality.utils.Weather3hAdapter;
|
||||
import com.example.airquality.utils.Weather3hParser;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public abstract class JsonAPIRequest {
|
||||
|
||||
private Context appContext;
|
||||
protected String url;
|
||||
|
||||
public JsonAPIRequest(Context context)
|
||||
{
|
||||
this.appContext = context;
|
||||
}
|
||||
|
||||
protected String getKey()
|
||||
{
|
||||
return this.appContext.getString(R.string.weather_api_key);
|
||||
}
|
||||
public abstract JsonObjectRequest getRequest();
|
||||
}
|
||||
15
app/src/main/java/com/example/airquality/types/City.java
Normal file
15
app/src/main/java/com/example/airquality/types/City.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.example.airquality.types;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class City implements Serializable {
|
||||
public String name;
|
||||
public double latitude;
|
||||
public double longitude;
|
||||
|
||||
public City(String name, double latitude, double longitude) {
|
||||
this.name = name;
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.example.airquality.types;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.example.airquality.utils.PreferencesManager;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class FormattedTemp {
|
||||
public String tempText;
|
||||
public String tempMinText;
|
||||
public String tempMaxText;
|
||||
|
||||
public FormattedTemp(Context context, double temp, double tempMin, double tempMax)
|
||||
{
|
||||
String units = PreferencesManager.getUnits(context);
|
||||
|
||||
String suffix = units.equals("metric") ? "°C" : "°F";
|
||||
tempText = temp + suffix;
|
||||
tempMinText = tempMin + suffix;
|
||||
tempMaxText = tempMax + suffix;
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,16 @@
|
||||
package com.example.airquality;
|
||||
package com.example.airquality.types;
|
||||
|
||||
|
||||
public class Weather3h {
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Weather3h implements Serializable {
|
||||
private int dt;
|
||||
private String dateTime;
|
||||
private double temp;
|
||||
private double tempMin;
|
||||
private double tempMax;
|
||||
private int pressure;
|
||||
private int humidity;
|
||||
private double windSpeed;
|
||||
@ -11,10 +18,13 @@ package com.example.airquality;
|
||||
private String description;
|
||||
private String icon;
|
||||
|
||||
public Weather3h(String dateTime, double temp, int pressure, int humidity,
|
||||
public Weather3h(int dt, String dateTime, double temp, double tempMin, double tempMax, int pressure, int humidity,
|
||||
double windSpeed, int windDeg, String description, String icon) {
|
||||
this.dt = dt;
|
||||
this.dateTime = dateTime;
|
||||
this.temp = temp;
|
||||
this.tempMin = tempMin;
|
||||
this.tempMax = tempMax;
|
||||
this.pressure = pressure;
|
||||
this.humidity = humidity;
|
||||
this.windSpeed = windSpeed;
|
||||
@ -31,6 +41,22 @@ package com.example.airquality;
|
||||
return temp;
|
||||
}
|
||||
|
||||
public double getTempMin() {
|
||||
return tempMin;
|
||||
}
|
||||
|
||||
public double getTempMax() {
|
||||
return tempMax;
|
||||
}
|
||||
|
||||
public FormattedTemp formattedTemp(Context context) {
|
||||
return new FormattedTemp(context, temp, tempMin, tempMax);
|
||||
}
|
||||
|
||||
public int getDt() {
|
||||
return dt;
|
||||
}
|
||||
|
||||
public int getPressure() {
|
||||
return pressure;
|
||||
}
|
||||
@ -51,7 +77,9 @@ package com.example.airquality;
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getIcon() {
|
||||
return icon;
|
||||
public String getIconCode() { return icon; }
|
||||
public String getIconUrl() {
|
||||
|
||||
return "https://openweathermap.org/img/wn/" + icon + "@4x.png";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.example.airquality.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class BaseCompatActivity extends AppCompatActivity {
|
||||
public boolean checkInternet()
|
||||
{
|
||||
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
|
||||
return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
|
||||
}
|
||||
}
|
||||
@ -1,27 +1,27 @@
|
||||
package com.example.airquality;
|
||||
package com.example.airquality.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.example.airquality.types.City;
|
||||
|
||||
public class PreferencesManager {
|
||||
|
||||
private static final String PREFS_NAME = "MyPrefs";
|
||||
private static final String KEY_CITY = "city";
|
||||
private static final String KEY_DAYS = "days";
|
||||
private static final String KEY_UNITS = "units";
|
||||
|
||||
public static void savePreferences(Context context, String city, int days, String units) {
|
||||
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString(KEY_CITY, city);
|
||||
editor.putInt(KEY_DAYS, days);
|
||||
editor.putString(KEY_UNITS, units);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static String getCity(Context context) {
|
||||
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||
return prefs.getString(KEY_CITY, "Subotica"); // default: Subotica
|
||||
public static City getCity(Context context) {
|
||||
// DAVID: Realizovati iz sqlite
|
||||
return new City("Subotica", 46.1, 19.6667);
|
||||
}
|
||||
|
||||
public static int getDays(Context context) {
|
||||
@ -0,0 +1,56 @@
|
||||
package com.example.airquality.utils;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.MenuInflater;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.example.airquality.R;
|
||||
import com.example.airquality.SettingsActivity;
|
||||
|
||||
public abstract class ToolbarCompatActivity extends BaseCompatActivity {
|
||||
|
||||
protected Toolbar toolbar;
|
||||
protected void onRefreshOptionToolbar() { }
|
||||
|
||||
public boolean onCreateOptionsMenu(android.view.Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
|
||||
inflater.inflate(R.menu.menu_main, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(android.view.MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_refresh:
|
||||
onRefreshOptionToolbar();
|
||||
return true;
|
||||
|
||||
case R.id.menu_settings:
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
protected void initToolbar() {
|
||||
toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// Display application icon in the toolbar
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
getSupportActionBar().setLogo(R.drawable.weather_clear_symbolic);
|
||||
getSupportActionBar().setDisplayUseLogoEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setToolbarTitle(String title)
|
||||
{
|
||||
toolbar.setTitle(title);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.example.airquality.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.airquality.DetailsActivity;
|
||||
import com.example.airquality.MainActivity;
|
||||
import com.example.airquality.R;
|
||||
import com.example.airquality.types.City;
|
||||
import com.example.airquality.types.FormattedTemp;
|
||||
import com.example.airquality.types.Weather3h;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Weather3hAdapter extends RecyclerView.Adapter<Weather3hAdapter.WeatherViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private List<Weather3h> weatherList;
|
||||
private City city;
|
||||
|
||||
public Weather3hAdapter(Context context, List<Weather3h> weatherList, City city) {
|
||||
this.context = context;
|
||||
this.weatherList = weatherList;
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
// ViewHolder описывает и хранит ссылки на элементы layout
|
||||
public static class WeatherViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView txtDate, txtTemp, txtDesc;
|
||||
|
||||
public WeatherViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
txtDate = itemView.findViewById(R.id.txtDate);
|
||||
txtTemp = itemView.findViewById(R.id.txtTemp);
|
||||
txtDesc = itemView.findViewById(R.id.txtDesc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeatherViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.item_weather3h, parent, false);
|
||||
return new WeatherViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(WeatherViewHolder holder, int position) {
|
||||
Weather3h item = weatherList.get(position);
|
||||
FormattedTemp formattedTemp = item.formattedTemp(context);
|
||||
|
||||
holder.txtDate.setText(item.getDateTime());
|
||||
holder.txtTemp.setText(formattedTemp.tempText);
|
||||
holder.txtDesc.setText(item.getDescription());
|
||||
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(context, DetailsActivity.class);
|
||||
intent.putExtra("WEATHER_3H", item);
|
||||
intent.putExtra("CITY", city);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return weatherList.size();
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
package com.example.airquality;
|
||||
package com.example.airquality.utils;
|
||||
|
||||
import com.example.airquality.types.Weather3h;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
@ -6,19 +8,22 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Weather3hParser {
|
||||
public static List<Weather3h> parse(JSONObject jsonObject, int maxPoints) {
|
||||
public static Weather3h[] parse(JSONObject jsonObject) {
|
||||
List<Weather3h> forecastList = new ArrayList<>();
|
||||
|
||||
try {
|
||||
JSONArray listArray = jsonObject.getJSONArray("list");
|
||||
|
||||
for (int i = 0; i < listArray.length() && i < maxPoints; i++) {
|
||||
for (int i = 0; i < listArray.length(); i++) {
|
||||
JSONObject item = listArray.getJSONObject(i);
|
||||
int dt = item.getInt("dt");
|
||||
|
||||
String dateTime = item.getString("dt_txt");
|
||||
|
||||
JSONObject main = item.getJSONObject("main");
|
||||
double temp = main.getDouble("temp");
|
||||
double tempMin = main.getDouble("temp_min");
|
||||
double tempMax = main.getDouble("temp_max");
|
||||
int pressure = main.getInt("pressure");
|
||||
int humidity = main.getInt("humidity");
|
||||
|
||||
@ -30,7 +35,7 @@ public class Weather3hParser {
|
||||
double windSpeed = wind.getDouble("speed");
|
||||
int windDeg = wind.getInt("deg");
|
||||
|
||||
Weather3h weather3h = new Weather3h(dateTime, temp, pressure, humidity, windSpeed, windDeg, description, icon);
|
||||
Weather3h weather3h = new Weather3h(dt, dateTime, temp, tempMin, tempMax, pressure, humidity, windSpeed, windDeg, description, icon);
|
||||
forecastList.add(weather3h);
|
||||
}
|
||||
|
||||
@ -38,7 +43,7 @@ public class Weather3hParser {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return forecastList;
|
||||
return forecastList.toArray(new Weather3h[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,83 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".AQActivity">
|
||||
|
||||
<!-- AppBar layout for using Toolbar as AppBar -->
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- ToolBar widget -->
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#0F9D58"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:theme="?attr/actionBarTheme"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:title="Air Pollution"
|
||||
app:titleTextColor="#ffff" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/appBarLayout"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:padding="20dp"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvCity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvComponents"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView"
|
||||
android:textSize="24sp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvAQ" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAQ"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView"
|
||||
android:textSize="24sp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvCity" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -1,23 +1,143 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
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">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
<include
|
||||
android:id="@+id/include_toolbar"
|
||||
layout="@layout/component_toolbar" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/include_toolbar"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:padding="20dp"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewDetailsTitle"
|
||||
<LinearLayout
|
||||
android:id="@+id/headerInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Weather Details"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingBottom="12dp" />
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<!-- Ovde ćemo kasnije dodati detalje o pritisku, vlazi itd. -->
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/icon_code"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Привет!"
|
||||
android:textSize="14sp"
|
||||
android:layout_gravity="center"
|
||||
android:padding="4dp"/>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cityText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="City name"
|
||||
android:textStyle="bold"
|
||||
android:textSize="20sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/datetimeText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Date time"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tempWeatherText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="21 C | Cloudy"
|
||||
android:textSize="16sp"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:stretchColumns="1,2"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/headerInfo">
|
||||
|
||||
<TableRow>
|
||||
|
||||
<TextView
|
||||
android:padding="8dp"
|
||||
android:text="Temperature" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tempText"
|
||||
android:padding="8dp"
|
||||
android:text="12C ~ 21C" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
|
||||
<TextView
|
||||
android:padding="8dp"
|
||||
android:text="Pressure" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pressureText"
|
||||
android:padding="8dp"
|
||||
android:text="32 hPa" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView
|
||||
android:padding="8dp"
|
||||
android:text="Humidity" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/humidityText"
|
||||
android:padding="8dp"
|
||||
android:text="23%" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView
|
||||
android:padding="8dp"
|
||||
android:text="Wind speed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/windSpeedText"
|
||||
android:padding="8dp"
|
||||
android:text="21 m/s" />
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -7,46 +7,18 @@
|
||||
android:background="@color/white"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<!-- AppBar layout for using Toolbar as AppBar -->
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- ToolBar widget -->
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#0F9D58"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:theme="?attr/actionBarTheme"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:title="Weather Forcast"
|
||||
app:titleTextColor="#ffff" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
<include
|
||||
android:id="@+id/include_toolbar"
|
||||
layout="@layout/component_toolbar" />
|
||||
|
||||
<!-- TextView of the Activity -->
|
||||
<ListView
|
||||
android:id="@+id/listView"
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/weatherList"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:divider="@android:color/darker_gray"
|
||||
android:dividerHeight="1dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/appBarLayout"
|
||||
app:layout_constraintTop_toBottomOf="@id/include_toolbar"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
@ -101,13 +101,6 @@
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="#0F9D58" />
|
||||
|
||||
<!-- ZAPAMTI ME -->
|
||||
<CheckBox
|
||||
android:id="@+id/checkBoxRemember"
|
||||
android:text="Remember my settings"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<!-- DUGME -->
|
||||
<Button
|
||||
|
||||
33
app/src/main/res/layout/component_toolbar.xml
Normal file
33
app/src/main/res/layout/component_toolbar.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- AppBar layout for using Toolbar as AppBar -->
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- ToolBar widget -->
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#0F9D58"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:theme="?attr/actionBarTheme"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:title="Weather"
|
||||
app:titleTextColor="#ffff" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
@ -1,4 +1,12 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="12dp">
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<TextView android:id="@+id/txtDate"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="DateTime"
|
||||
@ -14,4 +22,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Description"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#CCCCCC"
|
||||
android:layout_marginTop="12dp"/>
|
||||
</LinearLayout>
|
||||
@ -1,14 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_refresh"
|
||||
android:title="Refresh"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/menu_settings"
|
||||
android:title="Settings"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/menu_aq"
|
||||
android:title="Air Quality"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/menu_about"
|
||||
android:title="About"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user