diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/CarouselViewChallenge.Android.csproj b/CarouselViewChallenge/CarouselViewChallenge.Android/CarouselViewChallenge.Android.csproj index 1e33499..945a2da 100644 --- a/CarouselViewChallenge/CarouselViewChallenge.Android/CarouselViewChallenge.Android.csproj +++ b/CarouselViewChallenge/CarouselViewChallenge.Android/CarouselViewChallenge.Android.csproj @@ -53,9 +53,18 @@ + + 1.68.0 + + + 2.4.11.982 + + + 2.4.11.982 + - - + + @@ -101,4 +110,4 @@ - + \ No newline at end of file diff --git a/CarouselViewChallenge/CarouselViewChallenge.Android/MainActivity.cs b/CarouselViewChallenge/CarouselViewChallenge.Android/MainActivity.cs index fd4e22a..993ec01 100644 --- a/CarouselViewChallenge/CarouselViewChallenge.Android/MainActivity.cs +++ b/CarouselViewChallenge/CarouselViewChallenge.Android/MainActivity.cs @@ -6,6 +6,7 @@ using Android.Views; using Android.Widget; using Android.OS; +using FFImageLoading.Forms.Platform; namespace CarouselViewChallenge.Droid { @@ -20,8 +21,10 @@ protected override void OnCreate(Bundle savedInstanceState) base.OnCreate(savedInstanceState); global::Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental"); + FFImageLoading.Forms.Platform.CachedImageRenderer.Init(enableFastRenderer: true); Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); + CachedImageRenderer.InitImageViewHandler(); LoadApplication(new App()); } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) diff --git a/CarouselViewChallenge/CarouselViewChallenge.iOS/AppDelegate.cs b/CarouselViewChallenge/CarouselViewChallenge.iOS/AppDelegate.cs index 949500f..562057c 100644 --- a/CarouselViewChallenge/CarouselViewChallenge.iOS/AppDelegate.cs +++ b/CarouselViewChallenge/CarouselViewChallenge.iOS/AppDelegate.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; - +using FFImageLoading.Forms.Platform; using Foundation; using UIKit; @@ -23,7 +23,9 @@ public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsAppli public override bool FinishedLaunching(UIApplication app, NSDictionary options) { global::Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental"); + FFImageLoading.Forms.Platform.CachedImageRenderer.Init(); global::Xamarin.Forms.Forms.Init(); + CachedImageRenderer.InitImageSourceHandler(); LoadApplication(new App()); return base.FinishedLaunching(app, options); diff --git a/CarouselViewChallenge/CarouselViewChallenge.iOS/CarouselViewChallenge.iOS.csproj b/CarouselViewChallenge/CarouselViewChallenge.iOS/CarouselViewChallenge.iOS.csproj index 6241d2c..7a6d802 100644 --- a/CarouselViewChallenge/CarouselViewChallenge.iOS/CarouselViewChallenge.iOS.csproj +++ b/CarouselViewChallenge/CarouselViewChallenge.iOS/CarouselViewChallenge.iOS.csproj @@ -129,8 +129,17 @@ + + 1.68.0 + + + 2.4.11.982 + + + 2.4.11.982 + - + @@ -139,4 +148,4 @@ CarouselViewChallenge - + \ No newline at end of file diff --git a/CarouselViewChallenge/CarouselViewChallenge/App.xaml b/CarouselViewChallenge/CarouselViewChallenge/App.xaml index f3469f1..b82ae9d 100644 --- a/CarouselViewChallenge/CarouselViewChallenge/App.xaml +++ b/CarouselViewChallenge/CarouselViewChallenge/App.xaml @@ -6,5 +6,17 @@ mc:Ignorable="d" x:Class="CarouselViewChallenge.App"> + + + #E8D6CB + #6683A9 + #192E4A + + + + #77abb7 + #476d7c + #1d3e53 + \ No newline at end of file diff --git a/CarouselViewChallenge/CarouselViewChallenge/CarouselViewChallenge.csproj b/CarouselViewChallenge/CarouselViewChallenge/CarouselViewChallenge.csproj index a58ec88..51b00ab 100644 --- a/CarouselViewChallenge/CarouselViewChallenge/CarouselViewChallenge.csproj +++ b/CarouselViewChallenge/CarouselViewChallenge/CarouselViewChallenge.csproj @@ -6,8 +6,11 @@ + + + - + diff --git a/CarouselViewChallenge/CarouselViewChallenge/Models/Sensor.cs b/CarouselViewChallenge/CarouselViewChallenge/Models/Sensor.cs new file mode 100644 index 0000000..8522229 --- /dev/null +++ b/CarouselViewChallenge/CarouselViewChallenge/Models/Sensor.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CarouselViewChallenge.Models +{ + public class Sensor + { + + public int Sensor_ID { get; set; } + + public string Name { get; set; } + + public double Temperature { get; set; } + + public double AvgTemperature { get; set; } + + public string imageSrc { get; set; } + + + public string TemperatureFormatted { get { + return "Current: "+Temperature + "\xB0"+"F"; + + } } + public string AvgTemperatureFormatted + { + get + { + return "Avg: "+AvgTemperature + "\xB0"+"F"; + } + } + + } +} diff --git a/CarouselViewChallenge/CarouselViewChallenge/ViewModels/BaseViewModel.cs b/CarouselViewChallenge/CarouselViewChallenge/ViewModels/BaseViewModel.cs new file mode 100644 index 0000000..a0073f5 --- /dev/null +++ b/CarouselViewChallenge/CarouselViewChallenge/ViewModels/BaseViewModel.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; + +namespace CarouselViewChallenge.ViewModels +{ + public class BaseViewModel : INotifyPropertyChanged + { + // public IDataStore DataStore => DependencyService.Get>() ?? new MockDataStore(); + public event PropertyChangedEventHandler PropertyChanged; + string _propTitle = string.Empty; + bool _propIsBusy; + bool isBusy = false; + public bool IsBusy + { + get { return _propIsBusy; } + set { SetProperty(ref _propIsBusy, value, "IsBusy"); } + } + + string title = string.Empty; + public string Title + { + get { return _propTitle; } + set { SetProperty(ref _propTitle, value, "Title"); } + } + + protected void SetProperty(ref T store, T value, string propName, Action onChanged = null) + { + if (EqualityComparer.Default.Equals(store, value)) + return; + store = value; + if (onChanged != null) + onChanged(); + OnPropertyChanged(propName); + } + + //#region INotifyPropertyChanged + //public event PropertyChangedEventHandler PropertyChanged; + public void OnPropertyChanged(string propName) + { + if (PropertyChanged == null) + return; + PropertyChanged(this, new PropertyChangedEventArgs(propName)); + } + //#endregion + } +} diff --git a/CarouselViewChallenge/CarouselViewChallenge/ViewModels/CarouselViewChallengePageViewModel.cs b/CarouselViewChallenge/CarouselViewChallenge/ViewModels/CarouselViewChallengePageViewModel.cs new file mode 100644 index 0000000..f9dc25b --- /dev/null +++ b/CarouselViewChallenge/CarouselViewChallenge/ViewModels/CarouselViewChallengePageViewModel.cs @@ -0,0 +1,49 @@ +using CarouselViewChallenge.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; + +namespace CarouselViewChallenge.ViewModels +{ + public class CarouselViewChallengePageViewModel:BaseViewModel + { + Dictionary sensorNameLocations; + ObservableCollection sensors = new ObservableCollection(); + + public CarouselViewChallengePageViewModel() { + + + sensorNameLocations = new Dictionary(); + sensorNameLocations.Add("Bar", "https://www.beveragefactory.com/images/MO24BNS1RS-built-in010516144751.jpg"); + sensorNameLocations.Add("Kitchen", "https://cdn-image.realsimple.com/sites/default/files/1537981754/matte-appliances-trend-kitchen.JPG"); + sensorNameLocations.Add("Bedroom", "https://www.ikea.com/ms/media/rooms/20201/bedroom/20201_rmbe05a/20201_rmbe05a_01_thumb_PH163122.jpg"); + sensorNameLocations.Add("Garage", "https://www.residencestyle.com/wp-content/uploads/2019/06/Garage.jpg"); + sensorNameLocations.Add("PC", "https://i.pinimg.com/originals/75/79/ee/7579ee363b374c6c02455b98a6eeaa6d.jpg"); + sensorNameLocations.Add("Attic", "https://49op3q1oapcpd3h2q1ys9f81-wpengine.netdna-ssl.com/wp-content/uploads/2017/08/attic-2416396_1920.jpg"); + sensorNameLocations.Add("Monkey Habitat", "https://pixfeeds.com/images/animals/monkeys/1280-669297382-sri-lankan-monkeys-at-yala-national-park.jpg"); + setupFakeData(); + } + + + + + + private void setupFakeData() + { + Random r = new Random(); + foreach (string s in sensorNameLocations.Keys) { + var temp = Math.Round(r.Next(30, 104) + r.NextDouble(),2); + Sensors.Add(new Sensor(){ Sensor_ID = 0,Name=s+" Sensor", Temperature=temp, AvgTemperature=temp+r.Next(-5,5), imageSrc= sensorNameLocations[s] }); + + } + } + + + public ObservableCollection Sensors + { + get { return sensors; } + set { SetProperty(ref sensors, value, "Sensors"); } + } + } +} diff --git a/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml b/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml index 1a7cc0d..04a7f86 100644 --- a/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml +++ b/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml @@ -3,11 +3,129 @@ 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:local="clr-namespace:CarouselViewChallenge.ViewModels" + xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms" + xmlns:fftransformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations" + xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms" mc:Ignorable="d" x:Class="CarouselViewChallenge.Views.CarouselViewChallengePage"> + + + + + + + + mountain_dark + + #FFFFFF + #768ea0 + #d2d7dd + #ffa318 + #FFFFFF + #FFFFFF + #ffffff + + + #E8D6CB + #6683A9 + #192E4A + + #7A89B1 + #FB7D80 + + + + LightGray + Black + Black + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml.cs b/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml.cs index 38f2e9f..17fe3cb 100644 --- a/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml.cs +++ b/CarouselViewChallenge/CarouselViewChallenge/Views/CarouselViewChallengePage.xaml.cs @@ -1,4 +1,6 @@ -using System; +using SkiaSharp; +using SkiaSharp.Views.Forms; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -16,5 +18,62 @@ public CarouselViewChallengePage() { InitializeComponent(); } + + SKPaint backgroundBrush = new SKPaint() + { + Style = SKPaintStyle.Fill, + Color = Color.Red.ToSKColor() + }; + + private void BackgroundGradient_PaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e) + { + SKImageInfo info = e.Info; + SKSurface surface = e.Surface; + SKCanvas canvas = surface.Canvas; + + canvas.Clear(); + + // get the brush based on the theme + SKColor gradientStart = ((Color)Application.Current.Resources["BackgroundGradientStartColor"]).ToSKColor(); + SKColor gradientMid = ((Color)Application.Current.Resources["BackgroundGradientMidColor"]).ToSKColor(); + SKColor gradientEnd = ((Color)Application.Current.Resources["BackgroundGradientEndColor"]).ToSKColor(); + + // gradient background with 3 colors + backgroundBrush.Shader = SKShader.CreateRadialGradient( + new SKPoint(0, info.Height * .8f), + info.Height * .8f, + new SKColor[] { gradientStart, gradientMid, gradientEnd }, + new float[] { 0, .5f, 1 }, + SKShaderTileMode.Clamp); + + SKRect backgroundBounds = new SKRect(0, 0, info.Width, info.Height); + canvas.DrawRect(backgroundBounds, backgroundBrush); + } + + + private void CarouselGradient_PaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e) + { + SKImageInfo info = e.Info; + SKSurface surface = e.Surface; + SKCanvas canvas = surface.Canvas; + + canvas.Clear(); + + // get the brush based on the theme + SKColor gradientStart = ((Color)Application.Current.Resources["CarouselGradientStartColor"]).ToSKColor(); + SKColor gradientMid = ((Color)Application.Current.Resources["CarouselGradientMidColor"]).ToSKColor(); + SKColor gradientEnd = ((Color)Application.Current.Resources["CarouselGradientEndColor"]).ToSKColor(); + + // gradient background with 3 colors + backgroundBrush.Shader = SKShader.CreateLinearGradient( + new SKPoint(0, 0), + new SKPoint(info.Width, info.Height), + new SKColor[] { gradientStart, gradientMid, gradientEnd }, + new float[] { 0, .5f, 1 }, + SKShaderTileMode.Clamp); + + SKRect backgroundBounds = new SKRect(0, 0, info.Width, info.Height); + canvas.DrawRoundRect(new SKRoundRect(backgroundBounds, 60, 60), backgroundBrush); + } } } \ No newline at end of file