diff --git a/README.md b/README.md index fea713d..fe0f043 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,27 @@ Efficient way to add a shimmering effect to your Xamarin.Forms applications. # Documentation -![Alt Text](https://media.giphy.com/media/AgON7bzysYW9UdXpJF/giphy.gif) # How To Use -ToDo the specifications. For now, check the sample. It's quite easy. +* Add nuget package Xamarin.Essentials to all projects +* Add Init method to ```App.cs``` constructor: +``` +InitializeComponent(); +var density = Xamarin.Essentials.DeviceDisplay.MainDisplayInfo.Density; +ShimmerLayout.Init(density); +``` +* add reference: +```xml +xmlns:controls="clr-namespace:XFShimmerLayout.Controls;assembly=XFShimmerLayout" +``` +* Paste content inside shimmerLayout: +```xml + + + +``` # How it works ## Drawing Process @@ -33,6 +48,27 @@ The ShimmerLayout will create a Canvas Layer above this StackLayout and will dra You can have as deep Visual Tree wants, the shimmer layout will draw a right copy of it. +## Round Corners and Padding + +You can set default CornerRadius and padding of overlay for every element, +```xml + +``` + + +or set for single element using Attached Property +```xml + + + +``` + + ## Shader Before drawing the Canvas, we must specify a Shader. We used a LinearGradient Shader. @@ -52,4 +88,4 @@ To make the animation happen, we need startX and endX: * The StartX will be 0 - GradientSizeInPixels * The EndX will be the Width + GradientSizeInPixels -We created an animation that animates a value from the StartX to EndX and every time we ```InvalidateSurface``` of the ```Canvas```. \ No newline at end of file +We created an animation that animates a value from the StartX to EndX and every time we ```InvalidateSurface``` of the ```Canvas```. diff --git a/every.png b/every.png new file mode 100644 index 0000000..006afb1 Binary files /dev/null and b/every.png differ diff --git a/single.png b/single.png new file mode 100644 index 0000000..01bca08 Binary files /dev/null and b/single.png differ diff --git a/src/Sample/XFShimmerLayoutSample/XFShimmerLayoutSample.Android/Resources/Resource.designer.cs b/src/Sample/XFShimmerLayoutSample/XFShimmerLayoutSample.Android/Resources/Resource.designer.cs index 8f2118d..93339a5 100644 --- a/src/Sample/XFShimmerLayoutSample/XFShimmerLayoutSample.Android/Resources/Resource.designer.cs +++ b/src/Sample/XFShimmerLayoutSample/XFShimmerLayoutSample.Android/Resources/Resource.designer.cs @@ -1,11 +1,11 @@ #pragma warning disable 1591 //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// Этот код создан программой. +// Исполняемая версия:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае +// повторной генерации кода. // //------------------------------------------------------------------------------ diff --git a/src/XFShimmerLayout/Controls/ShimmerLayout.cs b/src/XFShimmerLayout/Controls/ShimmerLayout.cs index 46ea233..81644fe 100644 --- a/src/XFShimmerLayout/Controls/ShimmerLayout.cs +++ b/src/XFShimmerLayout/Controls/ShimmerLayout.cs @@ -1,9 +1,9 @@ -using System; +using SkiaSharp; +using SkiaSharp.Views.Forms; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using SkiaSharp; -using SkiaSharp.Views.Forms; using Xamarin.Forms; using Xamarin.Forms.Internals; using XFShimmerLayout.Extensions; @@ -106,6 +106,56 @@ public int Angle set => SetValue(AngleProperty, value); } + public CornerRadius CornerRadiusOverlayDefault + { + get => (CornerRadius)GetValue(CornerRadiusOverlayDefaultProperty); + set => SetValue(CornerRadiusOverlayDefaultProperty, value); + } + + public static readonly BindableProperty CornerRadiusOverlayDefaultProperty = BindableProperty.Create( + nameof(CornerRadiusOverlayDefault), typeof(CornerRadius), typeof(ShimmerLayout), default(CornerRadius)); + + + public Thickness PaddingOverlayDefault + { + get => (Thickness)GetValue(PaddingOverlayDefaultProperty); + set => SetValue(PaddingOverlayDefaultProperty, value); + } + + public static readonly BindableProperty PaddingOverlayDefaultProperty = BindableProperty.Create( + nameof(PaddingOverlayDefault), typeof(Thickness), typeof(ShimmerLayout), default(Thickness)); + + + #endregion + + + #region Attached Properties + + public static BindableProperty CornerRadiusOverlayProperty = BindableProperty.CreateAttached( + "CornerRadiusOverlay", typeof(CornerRadius), typeof(ShimmerLayout), default(CornerRadius)); + + public static CornerRadius GetCornerRadiusOverlay(BindableObject view) + { + return (CornerRadius)view.GetValue(CornerRadiusOverlayProperty); + } + + public static void SetCornerRadiusOverlay(BindableObject view, CornerRadius value) + { + view.SetValue(CornerRadiusOverlayProperty, value); + } + + public static BindableProperty PaddingOverlayProperty = BindableProperty.CreateAttached( + "PaddingOverlay", typeof(Thickness), typeof(ShimmerLayout), default(Thickness)); + + public static Thickness GetPaddingOverlay(BindableObject view) + { + return (Thickness)view.GetValue(PaddingOverlayProperty); + } + + public static void SetPaddingOverlay(BindableObject view, Thickness value) + { + view.SetValue(PaddingOverlayProperty, value); + } #endregion private static double _density; @@ -129,7 +179,7 @@ public ShimmerLayout() SizeChanged += ElementSizeChanged; } - + /// /// Initialized the ShimmerLayout by specifying the Device Density /// @@ -189,10 +239,10 @@ private void UpdatePackedView(View oldValue, View newValue) Children.Insert(0, newValue); } - + private void UpdateGradient() { - _gradientPositions = new [] + _gradientPositions = new[] { 0, .5f - GradientSize / 2, @@ -200,7 +250,7 @@ private void UpdateGradient() 1 }; - _gradientColors = new [] + _gradientColors = new[] { BackgroundGradientColor.ToSKColor(), ForegroundGradientColor.ToSKColor(), @@ -260,7 +310,7 @@ private async Task StartAnimation() var startValue = -gradientSizePixels; var endValue = gradientSizePixels + widthPixels; - var tasks = new [] + var tasks = new[] { Task.Run(async () => await _maskCanvasView.FadeTo(1, 250U, Easing.Linear)), Task.Run(async () => @@ -354,13 +404,32 @@ private void OnMaskCanvasPaintSurface(object sender, SKPaintSurfaceEventArgs arg paint.Shader = GetGradientShader(); /* Draw every VisualElement in our layout tree to the SKCanvas */ - foreach (var view in _childVisualElements) + foreach (var skElement in _childVisualElements) { - DrawSKVisualElement(view, args.Surface.Canvas, paint); + //Set cornerRadius and padding for every view + var corner = GetCornerRadiusOverlay(skElement.OriginalView); + var padding = GetPaddingOverlay(skElement.OriginalView); + + //If not set - set default value + if (corner == default) + corner = CornerRadiusOverlayDefault; + + if (padding == default) + padding = PaddingOverlayDefault; + + //If default and specific not set, use box or frame cornerRadius + if(corner != default || CornerRadiusOverlayDefault != default) + skElement.CornerRadius = corner; + + skElement.Padding = padding; + + DrawSKVisualElement(skElement, args.Surface.Canvas, paint); } } } + + /// /// Generates a Gradient Shader for the Canvas with the actual Shimmer /// @@ -433,9 +502,10 @@ added to it exactly or to parent layouts /* Generate Radii from CornerRadius */ var radii = skVisualElement.CornerRadius.ToRadiiSKPoints(_density); - + var padding = skVisualElement.Padding; /* Using the SKRect constructor, in width and height, we must add the offset X and Y */ - var rectangle = new SKRect(startX, startY, widthPixels + startX, heightPixels + startY); + var rectangle = new SKRect(startX - (float)padding.Left, startY - (float)padding.Top, + widthPixels + startX + (float)padding.Right, heightPixels + startY + (float)padding.Bottom); /* Create the Round Rectangle */ var roundRectangle = new SKRoundRect(); diff --git a/src/XFShimmerLayout/Extensions/SkiaExtensions.cs b/src/XFShimmerLayout/Extensions/SkiaExtensions.cs index c5008ae..a925eda 100644 --- a/src/XFShimmerLayout/Extensions/SkiaExtensions.cs +++ b/src/XFShimmerLayout/Extensions/SkiaExtensions.cs @@ -11,8 +11,7 @@ internal static class SkiaExtensions { public static SKVisualElement ToSKVisualElement(this View element) { - var visualElement = new SKVisualElement((float)element.X, (float)element.Y, (float)element.Width, (float)element.Height, element.Margin); - + var visualElement = new SKVisualElement((float)element.X, (float)element.Y, (float)element.Width, (float)element.Height, element.Margin, element); switch (element) { case BoxView boxView: @@ -28,7 +27,7 @@ public static SKVisualElement ToSKVisualElement(this View element) public static SKLayout ToSKLayout(this Layout layout) { - var layoutView = new SKLayout((float)layout.X, (float)layout.Y, (float)layout.Width, (float)layout.Height, layout.Margin); + var layoutView = new SKLayout((float)layout.X, (float)layout.Y, (float)layout.Width, (float)layout.Height, layout.Margin, layout); var children = new List(); diff --git a/src/XFShimmerLayout/Models/SkiaHelpers/SKLayout.cs b/src/XFShimmerLayout/Models/SkiaHelpers/SKLayout.cs index 0627f90..6857a7a 100644 --- a/src/XFShimmerLayout/Models/SkiaHelpers/SKLayout.cs +++ b/src/XFShimmerLayout/Models/SkiaHelpers/SKLayout.cs @@ -8,7 +8,7 @@ internal class SKLayout : SKVisualElement public Thickness Padding { get; set; } public IList Children { get; set; } - public SKLayout(float x, float y, float width, float height, Thickness margin) - : base(x, y, width, height, margin) { } + public SKLayout(float x, float y, float width, float height, Thickness margin, View view) + : base(x, y, width, height, margin, view) { } } } diff --git a/src/XFShimmerLayout/Models/SkiaHelpers/SKVisualElement.cs b/src/XFShimmerLayout/Models/SkiaHelpers/SKVisualElement.cs index 709de08..5a6c6e5 100644 --- a/src/XFShimmerLayout/Models/SkiaHelpers/SKVisualElement.cs +++ b/src/XFShimmerLayout/Models/SkiaHelpers/SKVisualElement.cs @@ -9,10 +9,12 @@ internal class SKVisualElement public float Width { get; } public float Height { get; } public Thickness Margin { get; } + public Thickness Padding { get; set; } public SKLayout Parent { get; set; } public CornerRadius CornerRadius { get; set; } + public View OriginalView { get;} - public SKVisualElement(float x, float y, float width, float height, Thickness margin) + public SKVisualElement(float x, float y, float width, float height, Thickness margin, View view) { X = x; Y = y; @@ -20,6 +22,7 @@ public SKVisualElement(float x, float y, float width, float height, Thickness ma Height = height; Margin = margin; CornerRadius = new CornerRadius(0); + OriginalView = view; } } }