diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/CarouselViewChallenge.Android.csproj b/CarouselViewChallenge/CarouselViewChallenge.Android/CarouselViewChallenge.Android.csproj
index 1e33499..132d035 100644
--- a/CarouselViewChallenge/CarouselViewChallenge.Android/CarouselViewChallenge.Android.csproj
+++ b/CarouselViewChallenge/CarouselViewChallenge.Android/CarouselViewChallenge.Android.csproj
@@ -53,9 +53,18 @@
+
+ 12.0.2
+
+
+ 3.0.0.5
+
-
-
+
+
+
+ 1.2.1
+
@@ -100,5 +109,35 @@
CarouselViewChallenge
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/clouds.png b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/clouds.png
new file mode 100644
index 0000000..ef2e9f7
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/clouds.png differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/cloudy.png b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/cloudy.png
new file mode 100644
index 0000000..288a40e
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/cloudy.png differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/drizzle.png b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/drizzle.png
new file mode 100644
index 0000000..0f14cb6
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/drizzle.png differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/haze.png b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/haze.png
new file mode 100644
index 0000000..f04122b
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/haze.png differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/london.jpg b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/london.jpg
new file mode 100644
index 0000000..5ff0f3a
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/london.jpg differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/mexicocity.jpg b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/mexicocity.jpg
new file mode 100644
index 0000000..ffb3cbc
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/mexicocity.jpg differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/prague.jpg b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/prague.jpg
new file mode 100644
index 0000000..16f6053
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/prague.jpg differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/rain.png b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/rain.png
new file mode 100644
index 0000000..b5e5d10
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/rain.png differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/venice.jpg b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/venice.jpg
new file mode 100644
index 0000000..e363b87
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/venice.jpg differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/zlin.jpg b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/zlin.jpg
new file mode 100644
index 0000000..b88b4ea
Binary files /dev/null and b/CarouselViewChallenge/CarouselViewChallenge.Android/Resources/drawable/zlin.jpg differ
diff --git a/CarouselViewChallenge/CarouselViewChallenge.UWP/CarouselViewChallenge.UWP.csproj b/CarouselViewChallenge/CarouselViewChallenge.UWP/CarouselViewChallenge.UWP.csproj
index 4b6b2c9..b5b2a89 100644
--- a/CarouselViewChallenge/CarouselViewChallenge.UWP/CarouselViewChallenge.UWP.csproj
+++ b/CarouselViewChallenge/CarouselViewChallenge.UWP/CarouselViewChallenge.UWP.csproj
@@ -145,9 +145,18 @@
+
+ 12.0.2
+
+
+ 3.0.0.5
+
-
-
+
+
+
+ 1.2.1
+
@@ -159,4 +168,4 @@
14.0
-
+
\ No newline at end of file
diff --git a/CarouselViewChallenge/CarouselViewChallenge.iOS/CarouselViewChallenge.iOS.csproj b/CarouselViewChallenge/CarouselViewChallenge.iOS/CarouselViewChallenge.iOS.csproj
index 6241d2c..98ce924 100644
--- a/CarouselViewChallenge/CarouselViewChallenge.iOS/CarouselViewChallenge.iOS.csproj
+++ b/CarouselViewChallenge/CarouselViewChallenge.iOS/CarouselViewChallenge.iOS.csproj
@@ -129,8 +129,17 @@
+
+ 12.0.2
+
+
+ 3.0.0.5
+
-
+
+
+ 1.2.1
+
@@ -139,4 +148,4 @@
CarouselViewChallenge
-
+
\ No newline at end of file
diff --git a/CarouselViewChallenge/CarouselViewChallenge/CarouselViewChallenge.csproj b/CarouselViewChallenge/CarouselViewChallenge/CarouselViewChallenge.csproj
index a58ec88..e1b43ae 100644
--- a/CarouselViewChallenge/CarouselViewChallenge/CarouselViewChallenge.csproj
+++ b/CarouselViewChallenge/CarouselViewChallenge/CarouselViewChallenge.csproj
@@ -6,12 +6,19 @@
+
+
+
+
+
+
-
+
+
-
+
diff --git a/CarouselViewChallenge/CarouselViewChallenge/Converters/TemperatureConverter.cs b/CarouselViewChallenge/CarouselViewChallenge/Converters/TemperatureConverter.cs
new file mode 100644
index 0000000..0378304
--- /dev/null
+++ b/CarouselViewChallenge/CarouselViewChallenge/Converters/TemperatureConverter.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Globalization;
+using Xamarin.Essentials;
+using Xamarin.Forms;
+
+namespace CarouselViewChallenge.Converters
+{
+ public class TemperatureConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var temp = UnitConverters.KelvinToCelsius((double)value);
+ return $"{temp:N2} °C";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return null;
+ }
+ }
+}
diff --git a/CarouselViewChallenge/CarouselViewChallenge/Converters/WindConverter.cs b/CarouselViewChallenge/CarouselViewChallenge/Converters/WindConverter.cs
new file mode 100644
index 0000000..c299544
--- /dev/null
+++ b/CarouselViewChallenge/CarouselViewChallenge/Converters/WindConverter.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Globalization;
+using Xamarin.Forms;
+
+namespace CarouselViewChallenge.Converters
+{
+ public class WindConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return $"Wind: {value} m/s";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return null;
+ }
+ }
+}
diff --git a/CarouselViewChallenge/CarouselViewChallenge/Converters/WindDirectionConverter.cs b/CarouselViewChallenge/CarouselViewChallenge/Converters/WindDirectionConverter.cs
new file mode 100644
index 0000000..a0a6f5d
--- /dev/null
+++ b/CarouselViewChallenge/CarouselViewChallenge/Converters/WindDirectionConverter.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Globalization;
+using Xamarin.Forms;
+
+namespace CarouselViewChallenge.Converters
+{
+ public class WindDirectionConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var degrees = (int)value;
+ var direction = string.Empty;
+
+ if (degrees == 0 || degrees == 360)
+ direction = "N";
+ else if (degrees < 90)
+ direction = "NE";
+ else if (degrees == 90)
+ direction = "E";
+ else if (degrees < 180)
+ direction = "SE";
+ else if (degrees == 180)
+ direction = "S";
+ else if (degrees < 270)
+ direction = "SW";
+ else if (degrees == 270)
+ direction = "W";
+ else if (degrees < 360)
+ direction = "NW";
+ else
+ direction = "N/A";
+
+ return $"{direction} ({degrees:N0})°";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return null;
+ }
+ }
+}
diff --git a/CarouselViewChallenge/CarouselViewChallenge/Data/cities.json b/CarouselViewChallenge/CarouselViewChallenge/Data/cities.json
new file mode 100644
index 0000000..a7ede58
--- /dev/null
+++ b/CarouselViewChallenge/CarouselViewChallenge/Data/cities.json
@@ -0,0 +1,194 @@
+[
+ {
+ "coord": {
+ "lon": -0.13,
+ "lat": 51.51
+ },
+ "weather": {
+ "id": 300,
+ "main": "Drizzle",
+ "description": "light intensity drizzle",
+ "icon": "drizzle.png"
+ },
+ "base": "stations",
+ "main": {
+ "temp": 280.32,
+ "pressure": 1012,
+ "humidity": 81,
+ "temp_min": 279.15,
+ "temp_max": 281.15
+ },
+ "visibility": 10000,
+ "wind": {
+ "speed": 4.1,
+ "deg": 80
+ },
+ "clouds": { "all": 90 },
+ "dt": 1485789600,
+ "sys": {
+ "type": 1,
+ "id": 5091,
+ "message": 0.0103,
+ "country": "GB",
+ "sunrise": 1485762037,
+ "sunset": 1485794875
+ },
+ "id": 2643743,
+ "name": "London",
+ "cod": 200,
+ "image": "london.jpg"
+ },
+ {
+ "coord": {
+ "lon": 17.67,
+ "lat": 49.23
+ },
+ "weather": {
+ "id": 500,
+ "main": "Rain",
+ "description": "light rain",
+ "icon": "rain.png"
+ },
+ "base": "stations",
+ "main": {
+ "temp": 288.52,
+ "pressure": 1008,
+ "humidity": 77,
+ "temp_min": 285.93,
+ "temp_max": 291.15
+ },
+ "visibility": 10000,
+ "wind": {
+ "speed": 2.1,
+ "deg": 190
+ },
+ "clouds": { "all": 0 },
+ "dt": 1569434876,
+ "sys": {
+ "type": 1,
+ "id": 6842,
+ "message": 0.0081,
+ "country": "CZ",
+ "sunrise": 1569386365,
+ "sunset": 1569429774
+ },
+ "id": 3061369,
+ "name": "Zlin",
+ "cod": 200,
+ "image": "zlin.jpg"
+ },
+ {
+ "coord": {
+ "lon": -99.13,
+ "lat": 19.43
+ },
+ "weather": {
+ "id": 721,
+ "main": "Haze",
+ "description": "haze",
+ "icon": "haze.png"
+ },
+ "base": "stations",
+ "main": {
+ "temp": 295.66,
+ "pressure": 1027,
+ "humidity": 53,
+ "temp_min": 294.15,
+ "temp_max": 298.15
+ },
+ "visibility": 6437,
+ "wind": {
+ "speed": 2.6,
+ "deg": 60
+ },
+ "clouds": { "all": 40 },
+ "dt": 1569435136,
+ "sys": {
+ "type": 1,
+ "id": 7146,
+ "message": 0.0144,
+ "country": "MX",
+ "sunrise": 1569414355,
+ "sunset": 1569457834
+ },
+ "id": 3530597,
+ "name": "Mexico City",
+ "cod": 200,
+ "image": "mexicocity.jpg"
+ },
+ {
+ "coord": {
+ "lon": -82.45,
+ "lat": 27.1
+ },
+ "weather": {
+ "id": 802,
+ "main": "Clouds",
+ "description": "scattered clouds",
+ "icon": "clouds.png"
+ },
+ "base": "stations",
+ "main": {
+ "temp": 304.69,
+ "pressure": 1013,
+ "humidity": 52,
+ "temp_min": 303.15,
+ "temp_max": 306.15
+ },
+ "visibility": 16093,
+ "wind": {
+ "speed": 4.6,
+ "deg": 330
+ },
+ "clouds": { "all": 40 },
+ "dt": 1569435177,
+ "sys": {
+ "type": 1,
+ "id": 6184,
+ "message": 0.0093,
+ "country": "US",
+ "sunrise": 1569410370,
+ "sunset": 1569453814
+ },
+ "id": 4176380,
+ "name": "Venice",
+ "cod": 200,
+ "image": "venice.jpg"
+ },
+ {
+ "coord": {
+ "lon": 14.42,
+ "lat": 50.09
+ },
+ "weather": {
+ "id": 801,
+ "main": "Clouds",
+ "description": "few clouds",
+ "icon": "cloudy.png"
+ },
+ "base": "stations",
+ "main": {
+ "temp": 287.83,
+ "pressure": 1009,
+ "humidity": 71,
+ "temp_min": 285.37,
+ "temp_max": 289.82
+ },
+ "visibility": 10000,
+ "wind": { "speed": 1 },
+ "clouds": { "all": 20 },
+ "dt": 1569435218,
+ "sys": {
+ "type": 1,
+ "id": 6848,
+ "message": 0.0084,
+ "country": "CZ",
+ "sunrise": 1569387146,
+ "sunset": 1569430552
+ },
+ "id": 3067696,
+ "name": "Prague",
+ "cod": 200,
+ "image": "prague.jpg"
+ }
+]
\ No newline at end of file
diff --git a/CarouselViewChallenge/CarouselViewChallenge/Models/WeatherModels.cs b/CarouselViewChallenge/CarouselViewChallenge/Models/WeatherModels.cs
new file mode 100644
index 0000000..0dcf849
--- /dev/null
+++ b/CarouselViewChallenge/CarouselViewChallenge/Models/WeatherModels.cs
@@ -0,0 +1,64 @@
+namespace CarouselViewChallenge.Models
+{
+ public class CityWeather
+ {
+ public Coord coord { get; set; }
+ public Weather Weather { get; set; }
+ public string @base { get; set; }
+ public Main Main { get; set; }
+ public int visibility { get; set; }
+ public Wind Wind { get; set; }
+ public Clouds clouds { get; set; }
+ public int dt { get; set; }
+ public Sys Sys { get; set; }
+ public int id { get; set; }
+ public string Name { get; set; }
+ public int cod { get; set; }
+ public string Image { get; set; }
+ }
+
+ public class Coord
+ {
+ public double lon { get; set; }
+ public double lat { get; set; }
+ }
+
+ public class Weather
+ {
+ public int id { get; set; }
+ public string Main { get; set; }
+ public string Description { get; set; }
+ public string Icon { get; set; }
+ }
+
+ public class Main
+ {
+ public double Temp { get; set; }
+ public int pressure { get; set; }
+ public int Humidity { get; set; }
+ public double temp_min { get; set; }
+ public double temp_max { get; set; }
+ }
+
+ public class Wind
+ {
+ public double Speed { get; set; }
+ public int Deg { get; set; }
+ }
+
+ public class Clouds
+ {
+ public int all { get; set; }
+ }
+
+ public class Sys
+ {
+ public int type { get; set; }
+ public int id { get; set; }
+ public double message { get; set; }
+ public string Country { get; set; }
+ public int sunrise { get; set; }
+ public int sunset { get; set; }
+ }
+
+}
diff --git a/CarouselViewChallenge/CarouselViewChallenge/Services/WeatherService.cs b/CarouselViewChallenge/CarouselViewChallenge/Services/WeatherService.cs
new file mode 100644
index 0000000..e8ef0a0
--- /dev/null
+++ b/CarouselViewChallenge/CarouselViewChallenge/Services/WeatherService.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Text;
+using System.Reflection;
+using System.Collections.Generic;
+
+using Newtonsoft.Json;
+using CarouselViewChallenge.Models;
+
+namespace CarouselViewChallenge.Services
+{
+ public static class WeatherService
+ {
+ public static List GetWeather()
+ {
+ var assembly = IntrospectionExtensions.GetTypeInfo(typeof(WeatherService)).Assembly;
+ var stream = assembly.GetManifestResourceStream("CarouselViewChallenge.Data.cities.json");
+
+ var text = string.Empty;
+
+ using (var reader = new System.IO.StreamReader(stream))
+ {
+ text = reader.ReadToEnd();
+ }
+
+ return JsonConvert.DeserializeObject>(text);
+ }
+ }
+}
diff --git a/CarouselViewChallenge/CarouselViewChallenge/ViewModels/BaseViewModel.cs b/CarouselViewChallenge/CarouselViewChallenge/ViewModels/BaseViewModel.cs
new file mode 100644
index 0000000..1d9b082
--- /dev/null
+++ b/CarouselViewChallenge/CarouselViewChallenge/ViewModels/BaseViewModel.cs
@@ -0,0 +1,15 @@
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace CarouselViewChallenge.ViewModels
+{
+ public class BaseViewModel : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
diff --git a/CarouselViewChallenge/CarouselViewChallenge/ViewModels/ChallengePageViewModel.cs b/CarouselViewChallenge/CarouselViewChallenge/ViewModels/ChallengePageViewModel.cs
new file mode 100644
index 0000000..73964d2
--- /dev/null
+++ b/CarouselViewChallenge/CarouselViewChallenge/ViewModels/ChallengePageViewModel.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Text;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+using CarouselViewChallenge.Models;
+using CarouselViewChallenge.Services;
+
+namespace CarouselViewChallenge.ViewModels
+{
+ public class ChallengePageViewModel : BaseViewModel
+ {
+ private ObservableCollection cities;
+
+ public ObservableCollection Cities
+ {
+ get { return cities; }
+ set { cities = value; OnPropertyChanged(); }
+ }
+
+ private List list;
+
+ private bool isBusy;
+
+ public bool IsBusy
+ {
+ get { return isBusy; }
+ set { isBusy = value; OnPropertyChanged(); }
+ }
+
+ public void LoadData()
+ {
+ IsBusy = true;
+
+ list = WeatherService.GetWeather();
+ Cities = new ObservableCollection(list);
+
+ IsBusy = false;
+ }
+
+ }
+}
diff --git a/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml b/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml
index 1a7cc0d..65c1f80 100644
--- a/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml
+++ b/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml
@@ -3,11 +3,161 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:converters="clr-namespace:CarouselViewChallenge.Converters"
mc:Ignorable="d"
+ Title="Weather Information"
+ xmlns:pv="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
+ xmlns:ic="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin"
x:Class="CarouselViewChallenge.Views.CarouselViewChallengePage">
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml.cs b/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml.cs
index 38f2e9f..8717ff4 100644
--- a/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml.cs
+++ b/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml.cs
@@ -1,20 +1,27 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-using Xamarin.Forms;
+using Xamarin.Forms;
using Xamarin.Forms.Xaml;
+using CarouselViewChallenge.ViewModels;
+
namespace CarouselViewChallenge.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CarouselViewChallengePage : ContentPage
{
+ ChallengePageViewModel vm;
+
public CarouselViewChallengePage()
{
InitializeComponent();
+
+ vm = new ChallengePageViewModel();
+ BindingContext = vm;
+ }
+
+ protected override void OnAppearing()
+ {
+ base.OnAppearing();
+ vm.LoadData();
}
}
}
\ No newline at end of file