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