├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── art ├── background_android.png ├── background_borders_android.png ├── contentViewAndroid.gif ├── cornerRadiiElevation-iOS.png ├── cornerRadiiElevation.png ├── corner_clipping_android.png ├── corner_clipping_ios.png └── searchBarAndroid.gif ├── nuget ├── XamarinBackgroundKit.Skia.nuspec └── XamarinBackgroundKit.nuspec └── src ├── XamarinBackgroundKit.Android ├── BackgroundKit.cs ├── Effects │ ├── BackgroundEffect.cs │ ├── BasePlatformEffect.cs │ └── NoButtonTextCapsEffect.cs ├── Extensions │ ├── GradientDrawableExtensions.cs │ ├── ViewExtensions.cs │ └── VisualElementRendererExtensions.cs ├── GradientProviders │ ├── BaseGradientProvider.cs │ ├── GradientProvidersContainer.cs │ ├── IGradientProvider.cs │ └── LinearGradientProvider.cs ├── OutlineProviders │ └── PathOutlineProvider.cs ├── PathProviders │ ├── ArcPathProvider.cs │ ├── BasePathProvider.cs │ ├── CirclePathProvider.cs │ ├── CornerClipPathProvider.cs │ ├── DiagonalPathProvider.cs │ ├── IPathProvider.cs │ ├── PathProvidersContainer.cs │ ├── RectPathProvider.cs │ ├── RoundRectPathProvider.cs │ └── TrianglePathProvider.cs ├── Properties │ └── AssemblyInfo.cs ├── Renderers │ ├── GradientStrokeDrawable.cs │ ├── MaterialBackgroundManager.cs │ ├── MaterialContentViewRenderer.cs │ ├── MaterialShapeManager.cs │ └── MaterialShapeViewRenderer.cs └── XamarinBackgroundKit.Android.csproj ├── XamarinBackgroundKit.iOS ├── BackgroundKit.cs ├── Effects │ ├── BackgroundEffect.cs │ └── BasePlatformEffect.cs ├── Extensions │ └── ViewExtensions.cs ├── GradientProviders │ ├── BaseGradientProvider.cs │ ├── GradientProvidersContainer.cs │ ├── IGradientProvider.cs │ └── LinearGradientProvider.cs ├── PathProviders │ ├── ArcPathProvider.cs │ ├── BasePathProvider.cs │ ├── CirclePathProvider.cs │ ├── CornerClipPathProvider.cs │ ├── DiagonalPathProvider.cs │ ├── IPathProvider.cs │ ├── PathProvidersContainer.cs │ ├── RectPathProvider.cs │ ├── RoundRectPathProvider.cs │ └── TrianglePathProvider.cs ├── Properties │ └── AssemblyInfo.cs ├── Renderers │ ├── GradientStrokeLayer.cs │ ├── MaterialBackgroundManager.cs │ ├── MaterialContentViewRenderer.cs │ ├── MaterialShapeManager.cs │ └── MaterialShapeViewRenderer.cs └── XamarinBackgroundKit.iOS.csproj ├── XamarinBackgroundKit.sln ├── XamarinBackgroundKit ├── Abstractions │ ├── IBackgroundElement.cs │ ├── IBackgroundShape.cs │ ├── IBorderElement.cs │ ├── IClickableElement.cs │ ├── ICornerElement.cs │ ├── IElevationElement.cs │ ├── IFocusableElement.cs │ ├── IFontElement.cs │ ├── IGradientElement.cs │ ├── IMaterialVisualElement.cs │ └── ITextElement.cs ├── Controls │ ├── Background.cs │ ├── Base │ │ ├── BackgroundElement.cs │ │ ├── BorderElement.cs │ │ ├── ClickableElement.cs │ │ ├── CornerElement.cs │ │ ├── ElevationElement.cs │ │ ├── FocusableElement.cs │ │ ├── FontElement.cs │ │ ├── GradientElement.cs │ │ └── TextElement.cs │ ├── BorderStyle.cs │ ├── Chips │ │ ├── BaseMaterialChip.cs │ │ ├── MaterialButtonChip.cs │ │ └── MaterialLabelChip.cs │ ├── GradientBrush.cs │ ├── GradientStop.cs │ ├── GradientType.cs │ ├── LinearGradientBrush.cs │ ├── MaterialCard.cs │ ├── MaterialContentView.cs │ └── MaterialShapeView.cs ├── Effects │ ├── BackgroundEffect.cs │ └── TextEffect.cs ├── Extensions │ ├── AngleExtensions.cs │ ├── BackgroundExtensions.cs │ ├── CommandExtensions.cs │ ├── CornerRadiusExtensions.cs │ ├── ElementExtensions.cs │ └── GradientsExtensions.cs ├── MarkupExtensions │ ├── BgProviderExtension.cs │ └── LinearGradientExtension.cs ├── Properties │ └── AssemblyInfo.cs ├── Shapes │ ├── Arc.cs │ ├── BaseShape.cs │ ├── Circle.cs │ ├── CornerClip.cs │ ├── Diagonal.cs │ ├── Rect.cs │ ├── RoundRect.cs │ ├── ShapeDirection.cs │ ├── ShapePosition.cs │ └── Triangle.cs └── XamarinBackgroundKit.csproj ├── XamarinBackgroundKitSample.Android ├── Assets │ └── AboutAssets.txt ├── MainActivity.cs ├── Properties │ ├── AndroidManifest.xml │ └── AssemblyInfo.cs ├── Resources │ ├── AboutResources.txt │ ├── drawable-hdpi │ │ ├── ic_done.png │ │ ├── ic_done_grey.png │ │ └── xamagon_preview.png │ ├── drawable-mdpi │ │ ├── ic_done.png │ │ └── ic_done_grey.png │ ├── drawable-xhdpi │ │ ├── ic_done.png │ │ ├── ic_done_grey.png │ │ └── xamagon_preview.png │ ├── drawable-xxhdpi │ │ ├── ic_done.png │ │ ├── ic_done_grey.png │ │ └── xamagon_preview.png │ ├── drawable-xxxhdpi │ │ ├── ic_done.png │ │ ├── ic_done_grey.png │ │ └── xamagon_preview.png │ ├── drawable │ │ └── launch_screen.axml │ ├── layout │ │ ├── Tabbar.axml │ │ └── Toolbar.axml │ ├── mipmap-anydpi-v26 │ │ ├── icon.xml │ │ └── icon_round.xml │ ├── mipmap-hdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ ├── mipmap-mdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ ├── mipmap-xhdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ ├── mipmap-xxhdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ ├── mipmap-xxxhdpi │ │ ├── icon.png │ │ └── launcher_foreground.png │ └── values │ │ ├── colors.xml │ │ └── styles.xml └── XamarinBackgroundKitSample.Android.csproj ├── XamarinBackgroundKitSample.iOS ├── AppDelegate.cs ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon1024.png │ │ ├── Icon120.png │ │ ├── Icon152.png │ │ ├── Icon167.png │ │ ├── Icon180.png │ │ ├── Icon20.png │ │ ├── Icon29.png │ │ ├── Icon40.png │ │ ├── Icon58.png │ │ ├── Icon60.png │ │ ├── Icon76.png │ │ ├── Icon80.png │ │ └── Icon87.png ├── Entitlements.plist ├── Info.plist ├── Main.cs ├── Properties │ └── AssemblyInfo.cs ├── Resources │ ├── Icon60.png │ ├── Icon60@2x.png │ ├── Icon60@3x.png │ ├── LaunchScreen.storyboard │ ├── ic_done.png │ ├── ic_done@2x.png │ ├── ic_done@3x.png │ ├── ic_done_grey.png │ ├── ic_done_grey@2x.png │ └── ic_done_grey@3x.png └── XamarinBackgroundKitSample.iOS.csproj └── XamarinBackgroundKitSample ├── App.xaml ├── App.xaml.cs ├── ColorPickerPage.xaml ├── ColorPickerPage.xaml.cs ├── ExploreViewsPage.xaml ├── ExploreViewsPage.xaml.cs ├── ExplorerPage.xaml ├── ExplorerPage.xaml.cs ├── IssuesGalleryViews ├── Issue41Page.xaml ├── Issue41Page.xaml.cs ├── Issue90Page.xaml └── Issue90Page.xaml.cs ├── MainPage.xaml ├── MainPage.xaml.cs ├── Models ├── ColorSource.cs └── Issue90 │ ├── Issue90GroupModel.cs │ ├── Issue90ItemModel.cs │ └── Issue90ViewModel.cs ├── PickerTestPage.xaml ├── PickerTestPage.xaml.cs ├── Properties └── AssemblyInfo.cs ├── ShapeExplorerPage.xaml ├── ShapeExplorerPage.xaml.cs └── XamarinBackgroundKitSample.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Dionysis Chasakis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /art/background_android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/art/background_android.png -------------------------------------------------------------------------------- /art/background_borders_android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/art/background_borders_android.png -------------------------------------------------------------------------------- /art/contentViewAndroid.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/art/contentViewAndroid.gif -------------------------------------------------------------------------------- /art/cornerRadiiElevation-iOS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/art/cornerRadiiElevation-iOS.png -------------------------------------------------------------------------------- /art/cornerRadiiElevation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/art/cornerRadiiElevation.png -------------------------------------------------------------------------------- /art/corner_clipping_android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/art/corner_clipping_android.png -------------------------------------------------------------------------------- /art/corner_clipping_ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/art/corner_clipping_ios.png -------------------------------------------------------------------------------- /art/searchBarAndroid.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/art/searchBarAndroid.gif -------------------------------------------------------------------------------- /nuget/XamarinBackgroundKit.Skia.nuspec: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Xamarin.Forms.BackgroundKit.Skia 5 | 1.3.0 6 | Xamarin.Forms.BackgroundKit.Skia 7 | ChasakisD 8 | ChasakisD 9 | false 10 | The way the Xamarin.Forms Background Customization in Xamarin.Forms should be 11 | Xamarin.Forms Background Customization Library for Skia Views 12 | https://github.com/ChasakisD/Xamarin.Forms.BackgroundKit 13 | LICENSE.md 14 | Copyright 2018 15 | background, material, cardview, card, corner, cornerradius, radius, border, ripple, gradient, elevation, xamarin, forms, android, xamarin.forms, ios 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 33 | 34 | 36 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /nuget/XamarinBackgroundKit.nuspec: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Xamarin.Forms.BackgroundKit 5 | 2.1.2 6 | Xamarin.Forms.BackgroundKit 7 | ChasakisD 8 | ChasakisD 9 | false 10 | The way the Xamarin.Forms Background Customization in Xamarin.Forms should be 11 | Xamarin.Forms Background Customization Library 12 | https://github.com/ChasakisD/Xamarin.Forms.BackgroundKit 13 | LICENSE.md 14 | Copyright 2018 15 | background, material, cardview, card, corner, cornerradius, radius, border, ripple, gradient, elevation, xamarin, forms, android, xamarin.forms, ios 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | 50 | 51 | 53 | 55 | 56 | 57 | 58 | 59 | 60 | 62 | 64 | 65 | 67 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/BackgroundKit.cs: -------------------------------------------------------------------------------- 1 | using Android.Content; 2 | using Android.Graphics; 3 | using Android.Util; 4 | using Android.Views; 5 | using Java.Interop; 6 | using XamarinBackgroundKit.Android.GradientProviders; 7 | using XamarinBackgroundKit.Android.PathProviders; 8 | using AApp = Android.App.Application; 9 | 10 | namespace XamarinBackgroundKit.Android 11 | { 12 | public static class BackgroundKit 13 | { 14 | private static double _density; 15 | internal static double Density 16 | { 17 | get 18 | { 19 | if (_density > 0) return _density; 20 | 21 | using (var displayMetrics = new DisplayMetrics()) 22 | { 23 | var windowService = AApp.Context.GetSystemService(Context.WindowService) 24 | ?.JavaCast(); 25 | 26 | using (var display = windowService?.DefaultDisplay) 27 | { 28 | if (display == null) return _density; 29 | 30 | display.GetRealMetrics(displayMetrics); 31 | _density = displayMetrics.Density; 32 | return _density; 33 | } 34 | } 35 | } 36 | } 37 | 38 | public static readonly PorterDuffXfermode PorterDuffClearMode = 39 | new PorterDuffXfermode(PorterDuff.Mode.Clear); 40 | 41 | public static readonly PorterDuffXfermode PorterDuffDstInMode = 42 | new PorterDuffXfermode(PorterDuff.Mode.DstIn); 43 | 44 | public static readonly PorterDuffXfermode PorterDuffDstOutMode = 45 | new PorterDuffXfermode(PorterDuff.Mode.DstOut); 46 | 47 | public static void Init() 48 | { 49 | PathProvidersContainer.Init(); 50 | GradientProvidersContainer.Init(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/Effects/BasePlatformEffect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Xamarin.Forms; 4 | using Xamarin.Forms.Platform.Android; 5 | using AView = Android.Views.View; 6 | 7 | namespace XamarinBackgroundKit.Android.Effects 8 | { 9 | public class BasePlatformEffect : PlatformEffect 10 | where TEffect : RoutingEffect 11 | where TElement : Element 12 | where TNativeView : AView 13 | { 14 | protected TEffect Effect; 15 | protected TElement XElement; 16 | protected TNativeView View; 17 | 18 | protected bool IsDisposed => 19 | (Container as IVisualElementRenderer)?.Element == null || 20 | View == null || View?.Handle == IntPtr.Zero; 21 | 22 | protected override void OnAttached() 23 | { 24 | View = (Control ?? Container) as TNativeView; 25 | XElement = Element as TElement; 26 | 27 | if (Element?.Effects == null || Element.Effects.Count == 0) return; 28 | Effect = (TEffect)Element.Effects.FirstOrDefault(x => x is TEffect); 29 | } 30 | 31 | protected override void OnDetached() 32 | { 33 | View = (Control ?? Container) as TNativeView; 34 | XElement = Element as TElement; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/Effects/NoButtonTextCapsEffect.cs: -------------------------------------------------------------------------------- 1 | using AndroidX.AppCompat.Widget; 2 | using Xamarin.Forms; 3 | using XamarinBackgroundKit.Android.Effects; 4 | using XamarinBackgroundKit.Effects; 5 | 6 | [assembly: ExportEffect(typeof(NoButtonTextCapsEffectDroid), nameof(NoButtonTextCapsEffect))] 7 | namespace XamarinBackgroundKit.Android.Effects 8 | { 9 | public class NoButtonTextCapsEffectDroid : BasePlatformEffect 10 | { 11 | protected override void OnAttached() 12 | { 13 | base.OnAttached(); 14 | 15 | View?.SetAllCaps(false); 16 | } 17 | 18 | protected override void OnDetached() 19 | { 20 | base.OnDetached(); 21 | 22 | if (IsDisposed) return; 23 | 24 | View?.SetAllCaps(true); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/Extensions/GradientDrawableExtensions.cs: -------------------------------------------------------------------------------- 1 | using Android.Graphics.Drawables; 2 | using static Android.Graphics.Drawables.GradientDrawable; 3 | 4 | namespace XamarinBackgroundKit.Android.Extensions 5 | { 6 | public static class GradientDrawableExtensions 7 | { 8 | public static void SetOrientation(this GradientDrawable drawable, float angle) 9 | { 10 | drawable.SetOrientation((double)angle); 11 | } 12 | 13 | public static void SetOrientation(this GradientDrawable drawable, double angle) 14 | { 15 | var orientation = angle >= 0 && angle < 45 ? Orientation.LeftRight : 16 | angle < 90 ? Orientation.BlTr : 17 | angle < 135 ? Orientation.BottomTop : 18 | angle < 180 ? Orientation.BrTl : 19 | angle < 225 ? Orientation.RightLeft : 20 | angle < 270 ? Orientation.TrBl : 21 | angle < 315 ? Orientation.TopBottom : Orientation.TlBr; 22 | 23 | drawable.SetOrientation(orientation); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/Extensions/VisualElementRendererExtensions.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms.Platform.Android; 2 | using AView = Android.Views.View; 3 | 4 | namespace XamarinBackgroundKit.Android.Extensions 5 | { 6 | public static class VisualElementRendererExtensions 7 | { 8 | public static AView ResolveViewFromRenderer(this IVisualElementRenderer renderer) 9 | { 10 | switch (renderer) 11 | { 12 | case EntryRenderer entryRenderer: 13 | return entryRenderer.Control; 14 | case IButtonLayoutRenderer buttonLayoutRenderer: 15 | return buttonLayoutRenderer.View; 16 | case IBorderVisualElementRenderer borderVisualElementRenderer: 17 | return borderVisualElementRenderer.View; 18 | default: 19 | return renderer.View; 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/GradientProviders/BaseGradientProvider.cs: -------------------------------------------------------------------------------- 1 | using Android.Graphics; 2 | using XamarinBackgroundKit.Controls; 3 | 4 | namespace XamarinBackgroundKit.Android.GradientProviders 5 | { 6 | public abstract class BaseGradientProvider : IGradientProvider where T : GradientBrush 7 | { 8 | private bool _disposed; 9 | 10 | public abstract bool HasGradient { get; protected set; } 11 | 12 | void IGradientProvider.SetGradient(GradientBrush gradientBrush) => 13 | OnGradientSet((T)gradientBrush); 14 | 15 | void IGradientProvider.DrawGradient(Paint paint, int width, int height) => 16 | DrawGradient(paint, width, height); 17 | 18 | public abstract void OnGradientSet(T gradientBrush); 19 | public abstract void DrawGradient(Paint paint, int width, int height); 20 | public abstract void ClearGradient(Paint paint, int width, int height); 21 | 22 | public virtual void DrawOrClearGradient(Paint paint, int width, int height) 23 | { 24 | if (!HasGradient) 25 | { 26 | ClearGradient(paint, width, height); 27 | return; 28 | } 29 | 30 | DrawGradient(paint, width, height); 31 | } 32 | 33 | public void Dispose() 34 | { 35 | if (_disposed) return; 36 | 37 | _disposed = true; 38 | Dispose(_disposed); 39 | } 40 | 41 | public virtual void Dispose(bool disposing) 42 | { 43 | 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/GradientProviders/GradientProvidersContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using XamarinBackgroundKit.Controls; 4 | 5 | namespace XamarinBackgroundKit.Android.GradientProviders 6 | { 7 | public static class GradientProvidersContainer 8 | { 9 | private static bool _isInitialized; 10 | 11 | private static readonly Lazy>> FactoriesLazy = 12 | new Lazy>>(() => new Dictionary>()); 13 | 14 | private static Dictionary> Factories => FactoriesLazy.Value; 15 | 16 | public static void Init() 17 | { 18 | _isInitialized = true; 19 | 20 | Register(() => new LinearGradientProvider()); 21 | } 22 | 23 | public static IGradientProvider Resolve() where TGradientBrush : GradientBrush 24 | { 25 | return Resolve(typeof(TGradientBrush)); 26 | } 27 | 28 | public static IGradientProvider Resolve(Type gradientBrushType) 29 | { 30 | if (!_isInitialized) 31 | { 32 | Init(); 33 | } 34 | 35 | if (!Factories.ContainsKey(gradientBrushType)) 36 | throw new Exception("Not found registered PathProvider"); 37 | 38 | return Factories[gradientBrushType](); 39 | } 40 | 41 | public static void Register(Func gradientProviderFactory) where TGradientBrush : GradientBrush 42 | { 43 | if (Factories.ContainsKey(typeof(TGradientBrush))) 44 | { 45 | Factories[typeof(TGradientBrush)] = gradientProviderFactory; 46 | return; 47 | } 48 | 49 | Factories.Add(typeof(TGradientBrush), gradientProviderFactory); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/GradientProviders/IGradientProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Android.Graphics; 3 | using XamarinBackgroundKit.Controls; 4 | 5 | namespace XamarinBackgroundKit.Android.GradientProviders 6 | { 7 | public interface IGradientProvider : IDisposable 8 | { 9 | bool HasGradient { get; } 10 | 11 | void SetGradient(GradientBrush gradientBrush); 12 | void DrawGradient(Paint paint, int width, int height); 13 | void ClearGradient(Paint paint, int width, int height); 14 | void DrawOrClearGradient(Paint paint, int width, int height); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/GradientProviders/LinearGradientProvider.cs: -------------------------------------------------------------------------------- 1 | using Android.Graphics; 2 | using Xamarin.Forms.Platform.Android; 3 | using XamarinBackgroundKit.Controls; 4 | using XamarinBackgroundKit.Extensions; 5 | using AColor = Android.Graphics.Color; 6 | 7 | namespace XamarinBackgroundKit.Android.GradientProviders 8 | { 9 | public class LinearGradientProvider : BaseGradientProvider 10 | { 11 | private int[] _colors; 12 | private float[] _positions; 13 | private float[] _colorPositions; 14 | 15 | public override bool HasGradient { get; protected set; } 16 | 17 | public override void OnGradientSet(LinearGradientBrush gradientBrush) 18 | { 19 | if (gradientBrush == null || gradientBrush.Gradients == null || gradientBrush.Gradients.Count < 2) 20 | { 21 | _colors = null; 22 | _positions = null; 23 | _colorPositions = null; 24 | 25 | HasGradient = false; 26 | return; 27 | } 28 | 29 | HasGradient = true; 30 | 31 | var positions = gradientBrush.Angle.ToStartEndPoint(); 32 | 33 | for (var i = 0; i < positions.Length; i++) 34 | { 35 | if (!(positions[i] > 1)) continue; 36 | positions[i] = 1; 37 | } 38 | 39 | _positions = positions; 40 | _colors = new int[gradientBrush.Gradients.Count]; 41 | _colorPositions = new float[gradientBrush.Gradients.Count]; 42 | for (var i = 0; i < gradientBrush.Gradients.Count; i++) 43 | { 44 | _colors[i] = gradientBrush.Gradients[i].Color.ToAndroid(); 45 | _colorPositions[i] = gradientBrush.Gradients[i].Offset; 46 | } 47 | } 48 | 49 | public override void DrawGradient(Paint paint, int width, int height) 50 | { 51 | if (!HasGradient) return; 52 | 53 | /* Color of paint will be ignored */ 54 | paint.Color = AColor.White; 55 | paint.SetShader(new LinearGradient( 56 | width * _positions[0], 57 | height * _positions[1], 58 | width * _positions[2], 59 | height * _positions[3], 60 | _colors, 61 | _colorPositions, 62 | Shader.TileMode.Clamp)); 63 | } 64 | 65 | public override void ClearGradient(Paint paint, int width, int height) 66 | { 67 | InvalidateArrays(); 68 | 69 | paint.SetShader(null); 70 | } 71 | 72 | public override void Dispose(bool disposing) 73 | { 74 | InvalidateArrays(); 75 | } 76 | 77 | private void InvalidateArrays() 78 | { 79 | _colors = null; 80 | _positions = null; 81 | _colorPositions = null; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/OutlineProviders/PathOutlineProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Android.Graphics; 3 | using Android.Views; 4 | using XamarinBackgroundKit.Android.PathProviders; 5 | 6 | namespace XamarinBackgroundKit.Android.OutlineProviders 7 | { 8 | public class PathOutlineProvider : ViewOutlineProvider 9 | { 10 | private readonly WeakReference _pathProvider; 11 | 12 | public PathOutlineProvider(IPathProvider pathProvider) 13 | { 14 | _pathProvider = new WeakReference(pathProvider); 15 | } 16 | 17 | public override void GetOutline(View view, Outline outline) 18 | { 19 | if (!_pathProvider.TryGetTarget(out var pathProvider) || pathProvider.Path == null) return; 20 | 21 | if (pathProvider is RectPathProvider) 22 | { 23 | outline.SetRect(0, 0, view.Width, view.Height); 24 | return; 25 | } 26 | 27 | if (pathProvider is RoundRectPathProvider roundRectPathProvider) 28 | { 29 | /* If corner radius is uniform, use view outline provider */ 30 | if (roundRectPathProvider.CanHandledByOutline) 31 | { 32 | outline.SetRoundRect(0, 0, view.Width, view.Height, roundRectPathProvider.CornerRadii[0]); 33 | return; 34 | } 35 | } 36 | 37 | var clipPath = pathProvider.CreatePath(view.Width, view.Height); 38 | if (clipPath == null || !clipPath.IsConvex) return; 39 | 40 | outline.SetConvexPath(clipPath); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/ArcPathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Android.Graphics; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.Android.PathProviders 6 | { 7 | public class ArcPathProvider : BasePathProvider 8 | { 9 | public override bool IsBorderSupported => false; 10 | 11 | public override void CreatePath(Path path, Arc shape, int width, int height) 12 | { 13 | var arcHeightAbs = (float) Math.Abs(BackgroundKit.Density * shape.ArcHeight); 14 | 15 | switch(shape.Position) 16 | { 17 | case ShapePosition.Left: 18 | if (shape.IsCropInside) 19 | { 20 | path.MoveTo(width, 0); 21 | path.LineTo(0, 0); 22 | path.QuadTo(arcHeightAbs * 2, height / 2f, 0, height); 23 | path.LineTo(width, height); 24 | path.Close(); 25 | } 26 | else 27 | { 28 | path.MoveTo(width, 0); 29 | path.LineTo(arcHeightAbs, 0); 30 | path.QuadTo(-arcHeightAbs, height / 2f, arcHeightAbs, height); 31 | path.LineTo(width, height); 32 | path.Close(); 33 | } 34 | break; 35 | case ShapePosition.Top: 36 | if (shape.IsCropInside) 37 | { 38 | path.MoveTo(0, height); 39 | path.LineTo(0, 0); 40 | path.QuadTo(width / 2f, 2 * arcHeightAbs, width, 0); 41 | path.LineTo(width, height); 42 | path.Close(); 43 | } 44 | else 45 | { 46 | path.MoveTo(0, arcHeightAbs); 47 | path.QuadTo(width / 2f, -arcHeightAbs, width, arcHeightAbs); 48 | path.LineTo(width, height); 49 | path.LineTo(0, height); 50 | path.Close(); 51 | } 52 | break; 53 | case ShapePosition.Right: 54 | if (shape.IsCropInside) 55 | { 56 | path.MoveTo(0, 0); 57 | path.LineTo(width, 0); 58 | path.QuadTo(width - arcHeightAbs * 2, height / 2f, width, height); 59 | path.LineTo(0, height); 60 | path.Close(); 61 | } 62 | else 63 | { 64 | path.MoveTo(0, 0); 65 | path.LineTo(width - arcHeightAbs, 0); 66 | path.QuadTo(width + arcHeightAbs, height / 2f, width - arcHeightAbs, height); 67 | path.LineTo(0, height); 68 | path.Close(); 69 | } 70 | break; 71 | case ShapePosition.Bottom: 72 | if (shape.IsCropInside) 73 | { 74 | path.MoveTo(0, 0); 75 | path.LineTo(0, height); 76 | path.QuadTo(width / 2f, height - 2 * arcHeightAbs, width, height); 77 | path.LineTo(width, 0); 78 | path.Close(); 79 | } 80 | else 81 | { 82 | path.MoveTo(0, 0); 83 | path.LineTo(0, height - arcHeightAbs); 84 | path.QuadTo(width / 2f, height + arcHeightAbs, width, height - arcHeightAbs); 85 | path.LineTo(width, 0); 86 | path.Close(); 87 | } 88 | break; 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/BasePathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Android.Graphics; 3 | using XamarinBackgroundKit.Shapes; 4 | using Rect = XamarinBackgroundKit.Shapes.Rect; 5 | 6 | namespace XamarinBackgroundKit.Android.PathProviders 7 | { 8 | public abstract class BasePathProvider : IPathProvider where TShape : class, IBackgroundShape 9 | { 10 | private bool _disposed; 11 | private IBackgroundShape _shape; 12 | 13 | public Path Path { get; private set; } 14 | public Path BorderPath { get; private set; } 15 | public bool IsPathDirty { get; private set; } 16 | public bool IsBorderPathDirty { get; private set; } 17 | 18 | public virtual bool CanHandledByOutline => false; 19 | 20 | public abstract bool IsBorderSupported { get; } 21 | 22 | protected BasePathProvider() 23 | { 24 | _shape = new Rect(); 25 | 26 | Path = new Path(); 27 | BorderPath = new Path(); 28 | 29 | Invalidate(); 30 | } 31 | 32 | public void Invalidate() 33 | { 34 | IsPathDirty = true; 35 | IsBorderPathDirty = true; 36 | } 37 | 38 | public Path CreatePath(int width, int height) 39 | { 40 | if (_disposed || Path.Handle == IntPtr.Zero) return null; 41 | 42 | /* If the path is not dirty return it */ 43 | if (!IsPathDirty || !(_shape is TShape tShape)) return Path; 44 | 45 | Path.Reset(); 46 | 47 | CreatePath(Path, tShape, width, height); 48 | 49 | IsPathDirty = false; 50 | 51 | return Path; 52 | } 53 | 54 | public Path CreateBorderedPath(int width, int height) 55 | { 56 | if (_disposed || Path.Handle == IntPtr.Zero) return null; 57 | 58 | /* If the path provider, does not support border, use the default */ 59 | if (!IsBorderSupported) return CreatePath(width, height); 60 | 61 | /* If the path is not dirty return it */ 62 | if (!IsBorderPathDirty || !(_shape is TShape tShape)) return BorderPath; 63 | 64 | /* If there is no need to create border, return the normal path */ 65 | if (!tShape.NeedsBorderInset) return CreatePath(width, height); 66 | 67 | var strokeWidth = (int)(tShape.BorderWidth * BackgroundKit.Density); 68 | 69 | BorderPath.Reset(); 70 | 71 | CreateBorderedPath(BorderPath, tShape, width, height, strokeWidth); 72 | 73 | IsBorderPathDirty = false; 74 | 75 | return BorderPath; 76 | } 77 | 78 | public virtual void SetShape(IBackgroundShape shape) 79 | { 80 | if (_disposed) return; 81 | 82 | _shape = shape; 83 | 84 | Invalidate(); 85 | } 86 | 87 | public abstract void CreatePath(Path path, TShape shape, int width, int height); 88 | 89 | public virtual void CreateBorderedPath(Path path, TShape shape, int width, int height, int strokeWidth) { } 90 | 91 | public void Dispose() => Dispose(true); 92 | 93 | public virtual void Dispose(bool disposing) 94 | { 95 | if (_disposed) return; 96 | 97 | _disposed = true; 98 | 99 | _shape = null; 100 | 101 | if (Path != null) 102 | { 103 | Path.Dispose(); 104 | Path = null; 105 | } 106 | 107 | if (BorderPath != null) 108 | { 109 | BorderPath.Dispose(); 110 | BorderPath = null; 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/CirclePathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Android.Graphics; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.Android.PathProviders 6 | { 7 | public class CirclePathProvider : BasePathProvider 8 | { 9 | public override bool IsBorderSupported => true; 10 | 11 | public override void CreatePath(Path path, Circle shape, int width, int height) 12 | { 13 | var radius = Math.Min(width, height) / 2f; 14 | 15 | path.AddCircle(width / 2f, height / 2f, radius, Path.Direction.Ccw); 16 | } 17 | 18 | public override void CreateBorderedPath(Path path, Circle shape, int width, int height, int strokeWidth) 19 | { 20 | var radius = (Math.Min(width, height) - strokeWidth) / 2f; 21 | 22 | path.AddCircle(width / 2f, height / 2f, radius, Path.Direction.Ccw); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/CornerClipPathProvider.cs: -------------------------------------------------------------------------------- 1 | using Android.Graphics; 2 | using XamarinBackgroundKit.Shapes; 3 | 4 | namespace XamarinBackgroundKit.Android.PathProviders 5 | { 6 | public class CornerClipPathProvider : BasePathProvider 7 | { 8 | public override bool IsBorderSupported => false; 9 | 10 | public override void CreatePath(Path path, CornerClip shape, int width, int height) 11 | { 12 | var density = BackgroundKit.Density; 13 | var topLeftClipSizePx = (int)(shape.ClipSize.TopLeft * density); 14 | var topRightClipSizePx = (int)(shape.ClipSize.TopRight * density); 15 | var bottomLeftClipSizePx = (int)(shape.ClipSize.BottomLeft * density); 16 | var bottomRightClipSizePx = (int)(shape.ClipSize.BottomRight * density); 17 | 18 | path.MoveTo(topLeftClipSizePx, 0); 19 | path.LineTo(width - topRightClipSizePx, 0); 20 | path.LineTo(width, topRightClipSizePx); 21 | path.LineTo(width, height - bottomRightClipSizePx); 22 | path.LineTo(width - bottomRightClipSizePx, height); 23 | path.LineTo(bottomLeftClipSizePx, height); 24 | path.LineTo(0, height - bottomLeftClipSizePx); 25 | path.LineTo(0, topLeftClipSizePx); 26 | path.LineTo(topLeftClipSizePx, 0); 27 | path.Close(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/DiagonalPathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Android.Graphics; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.Android.PathProviders 6 | { 7 | public class DiagonalPathProvider : BasePathProvider 8 | { 9 | public override bool IsBorderSupported => false; 10 | 11 | public override void CreatePath(Path path, Diagonal shape, int width, int height) 12 | { 13 | var angleAbs = Math.Abs(shape.Angle); 14 | var isDirLeft = shape.Direction == ShapeDirection.Left; 15 | var diagonalHeight = (float)(width * Math.Tan(Math.PI / 180 * angleAbs)); 16 | 17 | switch (shape.Position) 18 | { 19 | case ShapePosition.Left: 20 | if (isDirLeft) 21 | { 22 | path.MoveTo(diagonalHeight, 0); 23 | path.LineTo(width, 0); 24 | path.LineTo(width, height); 25 | path.LineTo(0, height); 26 | } 27 | else 28 | { 29 | path.MoveTo(0, 0); 30 | path.LineTo(width, 0); 31 | path.LineTo(width, height); 32 | path.LineTo(diagonalHeight, height); 33 | } 34 | break; 35 | case ShapePosition.Top: 36 | if (isDirLeft) 37 | { 38 | path.MoveTo(width, height); 39 | path.LineTo(width, diagonalHeight); 40 | path.LineTo(0, 0); 41 | path.LineTo(0, height); 42 | } 43 | else 44 | { 45 | path.MoveTo(width, height); 46 | path.LineTo(width, 0); 47 | path.LineTo(0, diagonalHeight); 48 | path.LineTo(0, height); 49 | } 50 | break; 51 | case ShapePosition.Bottom: 52 | if (isDirLeft) 53 | { 54 | path.MoveTo(0, 0); 55 | path.LineTo(width, 0); 56 | path.LineTo(width, height - diagonalHeight); 57 | path.LineTo(0, height); 58 | } 59 | else 60 | { 61 | path.MoveTo(width, height); 62 | path.LineTo(0, height - diagonalHeight); 63 | path.LineTo(0, 0); 64 | path.LineTo(width, 0); 65 | } 66 | break; 67 | case ShapePosition.Right: 68 | if (isDirLeft) 69 | { 70 | path.MoveTo(0, 0); 71 | path.LineTo(width, 0); 72 | path.LineTo(width - diagonalHeight, height); 73 | path.LineTo(0, height); 74 | } 75 | else 76 | { 77 | path.MoveTo(0, 0); 78 | path.LineTo(width - diagonalHeight, 0); 79 | path.LineTo(width, height); 80 | path.LineTo(0, height); 81 | } 82 | break; 83 | } 84 | 85 | path.Close(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/IPathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Android.Graphics; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.Android.PathProviders 6 | { 7 | public interface IPathProvider : IDisposable 8 | { 9 | Path Path { get; } 10 | bool IsPathDirty { get; } 11 | bool IsBorderPathDirty { get; } 12 | bool IsBorderSupported { get; } 13 | bool CanHandledByOutline { get; } 14 | 15 | void Invalidate(); 16 | void SetShape(IBackgroundShape shape); 17 | 18 | Path CreatePath(int width, int height); 19 | Path CreateBorderedPath(int width, int height); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/PathProvidersContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.Android.PathProviders 6 | { 7 | public static class PathProvidersContainer 8 | { 9 | private static bool _isInitialized; 10 | 11 | private static readonly Lazy>> FactoriesLazy = 12 | new Lazy>>(() => new Dictionary>()); 13 | 14 | private static Dictionary> Factories => FactoriesLazy.Value; 15 | 16 | public static void Init() 17 | { 18 | _isInitialized = true; 19 | 20 | Register(() => new ArcPathProvider()); 21 | Register(() => new RectPathProvider()); 22 | Register(() => new CirclePathProvider()); 23 | Register(() => new DiagonalPathProvider()); 24 | Register(() => new TrianglePathProvider()); 25 | Register(() => new RoundRectPathProvider()); 26 | Register(() => new CornerClipPathProvider()); 27 | } 28 | 29 | public static IPathProvider Resolve() where TShape : IBackgroundShape 30 | { 31 | return Resolve(typeof(TShape)); 32 | } 33 | 34 | public static IPathProvider Resolve(Type shapeType) 35 | { 36 | if (!_isInitialized) 37 | { 38 | Init(); 39 | } 40 | 41 | if (!Factories.ContainsKey(shapeType)) 42 | throw new Exception("Not found registered PathProvider"); 43 | 44 | return Factories[shapeType](); 45 | } 46 | 47 | public static void Register(Func pathProviderFactory) where TShape : IBackgroundShape 48 | { 49 | if (Factories.ContainsKey(typeof(TShape))) 50 | { 51 | Factories[typeof(TShape)] = pathProviderFactory; 52 | return; 53 | } 54 | 55 | Factories.Add(typeof(TShape), pathProviderFactory); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/RectPathProvider.cs: -------------------------------------------------------------------------------- 1 | using Android.Graphics; 2 | using Rect = XamarinBackgroundKit.Shapes.Rect; 3 | 4 | namespace XamarinBackgroundKit.Android.PathProviders 5 | { 6 | public class RectPathProvider : BasePathProvider 7 | { 8 | public override bool IsBorderSupported => true; 9 | 10 | public override void CreatePath(Path path, Rect shape, int width, int height) 11 | { 12 | path.AddRect(0, 0, width, height, Path.Direction.Cw); 13 | } 14 | 15 | public override void CreateBorderedPath(Path path, Rect shape, int width, int height, int strokeWidth) 16 | { 17 | path.AddRect(strokeWidth, strokeWidth, width - strokeWidth, height - strokeWidth, Path.Direction.Cw); 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/RoundRectPathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Android.Graphics; 4 | using XamarinBackgroundKit.Extensions; 5 | using XamarinBackgroundKit.Shapes; 6 | 7 | namespace XamarinBackgroundKit.Android.PathProviders 8 | { 9 | public class RoundRectPathProvider : BasePathProvider 10 | { 11 | public float[] CornerRadii = new float[8]; 12 | 13 | public override bool IsBorderSupported => true; 14 | 15 | public override bool CanHandledByOutline => 16 | !IsPathDirty && Math.Abs(CornerRadii.Sum() / CornerRadii.Length - CornerRadii[0]) < 0.0001; 17 | 18 | public override void CreatePath(Path path, RoundRect shape, int width, int height) 19 | { 20 | CornerRadii = shape.CornerRadius.ToRadii(BackgroundKit.Density); 21 | 22 | path.AddRoundRect(0, 0, width, height, CornerRadii, Path.Direction.Cw); 23 | } 24 | 25 | public override void CreateBorderedPath(Path path, RoundRect shape, int width, int height, int strokeWidth) 26 | { 27 | var cornerRadii = shape.CornerRadius.ToRadii(BackgroundKit.Density); 28 | 29 | for (var i = 0; i < cornerRadii.Length; i++) 30 | cornerRadii[i] -= cornerRadii[i] <= 0 ? 0 : strokeWidth; 31 | 32 | path.AddRoundRect(strokeWidth, strokeWidth, width - strokeWidth, height - strokeWidth, cornerRadii, Path.Direction.Cw); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/PathProviders/TrianglePathProvider.cs: -------------------------------------------------------------------------------- 1 | using Android.Graphics; 2 | using XamarinBackgroundKit.Shapes; 3 | 4 | namespace XamarinBackgroundKit.Android.PathProviders 5 | { 6 | public class TrianglePathProvider : BasePathProvider 7 | { 8 | public override bool IsBorderSupported => false; 9 | 10 | public override void CreatePath(Path path, Triangle shape, int width, int height) 11 | { 12 | path.MoveTo((float)shape.PointA.X * width, (float)shape.PointA.Y * height); 13 | path.LineTo((float)shape.PointB.X * width, (float)shape.PointB.Y * height); 14 | path.LineTo((float)shape.PointC.X * width, (float)shape.PointC.Y * height); 15 | path.Close(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using Xamarin.Forms; 4 | 5 | [assembly: AssemblyTitle("XamarinBackgroundKit.Android")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("XamarinBackgroundKit.Android")] 10 | [assembly: AssemblyCopyright("Copyright © 2018")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | [assembly: ComVisible(false)] 14 | 15 | [assembly: AssemblyVersion("1.0.0.0")] 16 | [assembly: AssemblyFileVersion("1.0.0.0")] 17 | 18 | [assembly: ResolutionGroupName("XamarinBackgroundKit")] 19 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/Renderers/MaterialContentViewRenderer.cs: -------------------------------------------------------------------------------- 1 | using Android.Content; 2 | using Android.Graphics; 3 | using Android.Views; 4 | using System.ComponentModel; 5 | using Android.Content.Res; 6 | using Xamarin.Forms; 7 | using Xamarin.Forms.Platform.Android; 8 | using XamarinBackgroundKit.Android.Renderers; 9 | using XamarinBackgroundKit.Controls; 10 | using AView = Android.Views.View; 11 | using View = Xamarin.Forms.View; 12 | 13 | [assembly: ExportRenderer(typeof(MaterialContentView), typeof(MaterialContentViewRenderer))] 14 | namespace XamarinBackgroundKit.Android.Renderers 15 | { 16 | public class MaterialContentViewRenderer : ViewRenderer, AView.IOnClickListener 17 | { 18 | private bool _disposed; 19 | private bool _isClickListenerSet; 20 | 21 | protected MaterialBackgroundManager BackgroundManager; 22 | 23 | private MaterialContentView ElementController => Element as MaterialContentView; 24 | 25 | public MaterialContentViewRenderer(Context context) : base(context) { } 26 | 27 | protected override void OnElementChanged(ElementChangedEventArgs e) 28 | { 29 | base.OnElementChanged(e); 30 | 31 | if (e.NewElement == null) return; 32 | 33 | this.EnsureId(); 34 | 35 | if (BackgroundManager == null) 36 | { 37 | BackgroundManager = new MaterialBackgroundManager(this); 38 | } 39 | 40 | UpdateAll(); 41 | } 42 | 43 | #region Clip Subviews 44 | 45 | protected override void OnLayout(bool changed, int l, int t, int r, int b) 46 | { 47 | base.OnLayout(changed, l, t, r, b); 48 | 49 | if (changed) 50 | { 51 | BackgroundManager?.Invalidate(); 52 | } 53 | } 54 | 55 | protected override void DispatchDraw(Canvas canvas) 56 | { 57 | BackgroundManager?.UpdateElevation(); 58 | 59 | BackgroundManager?.Draw(this, canvas, () => base.DispatchDraw(canvas)); 60 | } 61 | 62 | #endregion 63 | 64 | #region Property Changed 65 | 66 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) 67 | { 68 | if (_disposed) return; 69 | 70 | base.OnElementPropertyChanged(sender, e); 71 | 72 | if (e.PropertyName == MaterialContentView.IsFocusableProperty.PropertyName) UpdateIsFocusable(); 73 | else if (e.PropertyName == MaterialContentView.IsClickableProperty.PropertyName) UpdateIsClickable(); 74 | } 75 | 76 | private void UpdateAll() 77 | { 78 | UpdateIsFocusable(); 79 | UpdateIsClickable(); 80 | } 81 | 82 | private void UpdateIsFocusable() 83 | { 84 | Focusable = ElementController.IsFocusable; 85 | } 86 | 87 | private void UpdateIsClickable() 88 | { 89 | if (_isClickListenerSet && !ElementController.IsClickable) 90 | { 91 | Clickable = false; 92 | SetOnClickListener(null); 93 | _isClickListenerSet = false; 94 | } 95 | else if (!_isClickListenerSet && ElementController.IsClickable) 96 | { 97 | Clickable = true; 98 | SetOnClickListener(this); 99 | _isClickListenerSet = true; 100 | } 101 | } 102 | 103 | #endregion 104 | 105 | #region Touch Handling 106 | 107 | public override bool OnTouchEvent(MotionEvent e) 108 | { 109 | switch (e.Action) 110 | { 111 | case MotionEventActions.Down: 112 | ElementController?.OnPressed(); 113 | break; 114 | case MotionEventActions.Cancel: 115 | ElementController?.OnCancelled(); 116 | ElementController?.OnReleasedOrCancelled(); 117 | break; 118 | case MotionEventActions.Up: 119 | ElementController?.OnReleased(); 120 | ElementController?.OnReleasedOrCancelled(); 121 | break; 122 | } 123 | 124 | return base.OnTouchEvent(e); 125 | } 126 | 127 | #endregion 128 | 129 | #region Click Handling 130 | 131 | public void OnClick(AView v) 132 | { 133 | ElementController?.OnClicked(); 134 | } 135 | 136 | #endregion 137 | 138 | #region LifeCycle 139 | 140 | protected override void Dispose(bool disposing) 141 | { 142 | if (_disposed) return; 143 | 144 | _disposed = true; 145 | 146 | if (disposing) 147 | { 148 | if (BackgroundManager != null) 149 | { 150 | BackgroundManager.Dispose(); 151 | BackgroundManager = null; 152 | } 153 | 154 | if (_isClickListenerSet) 155 | { 156 | SetOnClickListener(null); 157 | } 158 | } 159 | 160 | base.Dispose(disposing); 161 | } 162 | 163 | #endregion 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/Renderers/MaterialShapeViewRenderer.cs: -------------------------------------------------------------------------------- 1 | using Android.Content; 2 | using System.ComponentModel; 3 | using Xamarin.Forms; 4 | using Xamarin.Forms.Platform.Android; 5 | using XamarinBackgroundKit.Android.Renderers; 6 | using XamarinBackgroundKit.Controls; 7 | using View = Xamarin.Forms.View; 8 | 9 | [assembly: ExportRenderer(typeof(MaterialShapeView), typeof(MaterialShapeViewRenderer))] 10 | namespace XamarinBackgroundKit.Android.Renderers 11 | { 12 | public class MaterialShapeViewRenderer : MaterialContentViewRenderer 13 | { 14 | private MaterialShapeView ElementController => Element as MaterialShapeView; 15 | 16 | public MaterialShapeViewRenderer(Context context) : base(context) { } 17 | 18 | protected override void OnElementChanged(ElementChangedEventArgs e) 19 | { 20 | base.OnElementChanged(e); 21 | 22 | UpdateShape(); 23 | } 24 | 25 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) 26 | { 27 | base.OnElementPropertyChanged(sender, e); 28 | 29 | if (e.PropertyName == MaterialShapeView.ShapeProperty.PropertyName) UpdateShape(); 30 | } 31 | 32 | private void UpdateShape() 33 | { 34 | BackgroundManager.SetShape(ElementController.Shape); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.Android/XamarinBackgroundKit.Android.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {FF4D0964-AEE1-4DE1-9864-E9402443569C} 9 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10 | {9ef11e43-1701-4396-8835-8392d57abb70} 11 | Library 12 | Properties 13 | XamarinBackgroundKit.Android 14 | XamarinBackgroundKit.Android 15 | 512 16 | Resources\Resource.designer.cs 17 | Off 18 | v10.0 19 | 20 | 21 | true 22 | portable 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 4.6.0.1180 79 | 80 | 81 | 82 | 83 | {54366595-a90d-4ac0-b816-fce69fa6410f} 84 | XamarinBackgroundKit 85 | 86 | 87 | 88 | 89 | 96 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/BackgroundKit.cs: -------------------------------------------------------------------------------- 1 | using XamarinBackgroundKit.iOS.GradientProviders; 2 | using XamarinBackgroundKit.iOS.PathProviders; 3 | 4 | namespace XamarinBackgroundKit.iOS 5 | { 6 | public static class BackgroundKit 7 | { 8 | public static void Init() 9 | { 10 | PathProvidersContainer.Init(); 11 | GradientProvidersContainer.Init(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/Effects/BasePlatformEffect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using UIKit; 4 | using Xamarin.Forms; 5 | using Xamarin.Forms.Platform.iOS; 6 | 7 | namespace XamarinBackgroundKit.iOS.Effects 8 | { 9 | public class BasePlatformEffect : PlatformEffect 10 | where TEffect : RoutingEffect 11 | where TElement : Element 12 | where TNativeView : UIView 13 | { 14 | protected TEffect Effect; 15 | protected TElement XElement; 16 | protected TNativeView View; 17 | 18 | protected bool IsDisposed => 19 | (Container as IVisualElementRenderer)?.Element == null || 20 | View == null || View.Handle == IntPtr.Zero; 21 | 22 | protected override void OnAttached() 23 | { 24 | View = (Control ?? Container) as TNativeView; 25 | XElement = Element as TElement; 26 | 27 | if (Element?.Effects == null || Element.Effects.Count == 0) return; 28 | Effect = (TEffect)Element.Effects.FirstOrDefault(x => x is TEffect); 29 | } 30 | 31 | protected override void OnDetached() 32 | { 33 | View = (Control ?? Container) as TNativeView; 34 | XElement = Element as TElement; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/GradientProviders/BaseGradientProvider.cs: -------------------------------------------------------------------------------- 1 | using CoreGraphics; 2 | using XamarinBackgroundKit.Controls; 3 | 4 | namespace XamarinBackgroundKit.iOS.GradientProviders 5 | { 6 | public abstract class BaseGradientProvider : IGradientProvider where T : GradientBrush 7 | { 8 | private bool _disposed; 9 | 10 | public abstract bool HasGradient { get; protected set; } 11 | 12 | void IGradientProvider.SetGradient(GradientBrush gradientBrush) => 13 | OnGradientSet((T)gradientBrush); 14 | 15 | void IGradientProvider.DrawGradient(CGContext ctx, CGRect bounds) => 16 | DrawGradient(ctx, bounds); 17 | 18 | public abstract void OnGradientSet(T gradientBrush); 19 | public abstract void DrawGradient(CGContext ctx, CGRect bounds); 20 | public abstract void ClearGradient(CGContext ctx, CGRect bounds); 21 | 22 | public virtual void DrawOrClearGradient(CGContext ctx, CGRect bounds) 23 | { 24 | if (!HasGradient) 25 | { 26 | ClearGradient(ctx, bounds); 27 | return; 28 | } 29 | 30 | DrawGradient(ctx, bounds); 31 | } 32 | 33 | public void Dispose() 34 | { 35 | if (_disposed) return; 36 | 37 | _disposed = true; 38 | Dispose(_disposed); 39 | } 40 | 41 | public virtual void Dispose(bool disposing) 42 | { 43 | 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/GradientProviders/GradientProvidersContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using XamarinBackgroundKit.Controls; 4 | 5 | namespace XamarinBackgroundKit.iOS.GradientProviders 6 | { 7 | public static class GradientProvidersContainer 8 | { 9 | private static bool _isInitialized; 10 | 11 | private static readonly Lazy>> FactoriesLazy = 12 | new Lazy>>(() => new Dictionary>()); 13 | 14 | private static Dictionary> Factories => FactoriesLazy.Value; 15 | 16 | public static void Init() 17 | { 18 | _isInitialized = true; 19 | 20 | Register(() => new LinearGradientProvider()); 21 | } 22 | 23 | public static IGradientProvider Resolve() where TGradientBrush : GradientBrush 24 | { 25 | return Resolve(typeof(TGradientBrush)); 26 | } 27 | 28 | public static IGradientProvider Resolve(Type shapeType) 29 | { 30 | if (!_isInitialized) 31 | { 32 | Init(); 33 | } 34 | 35 | if (!Factories.ContainsKey(shapeType)) 36 | throw new Exception("Not found registered PathProvider"); 37 | 38 | return Factories[shapeType](); 39 | } 40 | 41 | public static void Register(Func gradientProviderFactory) where TGradientBrush : GradientBrush 42 | { 43 | if (Factories.ContainsKey(typeof(TGradientBrush))) 44 | { 45 | Factories[typeof(TGradientBrush)] = gradientProviderFactory; 46 | return; 47 | } 48 | 49 | Factories.Add(typeof(TGradientBrush), gradientProviderFactory); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/GradientProviders/IGradientProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CoreGraphics; 3 | using XamarinBackgroundKit.Controls; 4 | 5 | namespace XamarinBackgroundKit.iOS.GradientProviders 6 | { 7 | public interface IGradientProvider : IDisposable 8 | { 9 | bool HasGradient { get; } 10 | 11 | void SetGradient(GradientBrush gradientBrush); 12 | void DrawGradient(CGContext ctx, CGRect bounds); 13 | void ClearGradient(CGContext ctx, CGRect bounds); 14 | void DrawOrClearGradient(CGContext ctx, CGRect bounds); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/GradientProviders/LinearGradientProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CoreGraphics; 3 | using Xamarin.Forms.Platform.iOS; 4 | using XamarinBackgroundKit.Controls; 5 | using XamarinBackgroundKit.Extensions; 6 | 7 | namespace XamarinBackgroundKit.iOS.GradientProviders 8 | { 9 | public class LinearGradientProvider : BaseGradientProvider 10 | { 11 | private CGColor[] _colors; 12 | private float[] _positions; 13 | private nfloat[] _colorPositions; 14 | 15 | public override bool HasGradient { get; protected set; } 16 | 17 | public override void OnGradientSet(LinearGradientBrush gradientBrush) 18 | { 19 | if (gradientBrush == null || gradientBrush == null || gradientBrush.Gradients.Count < 2) 20 | { 21 | _colors = null; 22 | _positions = null; 23 | _colorPositions = null; 24 | 25 | HasGradient = false; 26 | return; 27 | } 28 | 29 | HasGradient = true; 30 | 31 | var positions = gradientBrush.Angle.ToStartEndPoint(); 32 | 33 | for (var i = 0; i < positions.Length; i++) 34 | { 35 | if (!(positions[i] > 1)) continue; 36 | positions[i] = 1; 37 | } 38 | 39 | _positions = positions; 40 | _colors = new CGColor[gradientBrush.Gradients.Count]; 41 | _colorPositions = new nfloat[gradientBrush.Gradients.Count]; 42 | for (var i = 0; i < gradientBrush.Gradients.Count; i++) 43 | { 44 | _colors[i] = gradientBrush.Gradients[i].Color.ToCGColor(); 45 | _colorPositions[i] = gradientBrush.Gradients[i].Offset; 46 | } 47 | } 48 | 49 | public override void DrawGradient(CGContext ctx, CGRect bounds) 50 | { 51 | if (!HasGradient) return; 52 | 53 | var startPoint = new CGPoint(_positions[0] * bounds.Width, _positions[1] * bounds.Height); 54 | var endPoint = new CGPoint(_positions[2] * bounds.Width, _positions[3] * bounds.Height); 55 | 56 | var gradient = new CGGradient(CGColorSpace.CreateDeviceRGB(), _colors, _colorPositions); 57 | 58 | ctx.DrawLinearGradient(gradient, startPoint, endPoint, CGGradientDrawingOptions.None); 59 | } 60 | 61 | public override void ClearGradient(CGContext ctx, CGRect bounds) 62 | { 63 | InvalidateArrays(); 64 | } 65 | 66 | public override void Dispose(bool disposing) 67 | { 68 | InvalidateArrays(); 69 | } 70 | 71 | private void InvalidateArrays() 72 | { 73 | _colors = null; 74 | _positions = null; 75 | _colorPositions = null; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/PathProviders/BasePathProvider.cs: -------------------------------------------------------------------------------- 1 | using CoreGraphics; 2 | using XamarinBackgroundKit.Shapes; 3 | 4 | namespace XamarinBackgroundKit.iOS.PathProviders 5 | { 6 | public abstract class BasePathProvider : IPathProvider where TShape : class, IBackgroundShape 7 | { 8 | private bool _disposed; 9 | private IBackgroundShape _shape; 10 | 11 | public CGPath Path { get; set; } 12 | public CGPath BorderPath { get; set; } 13 | public bool IsPathDirty { get; private set; } 14 | public bool IsBorderPathDirty { get; private set; } 15 | 16 | public virtual bool CanHandledByOutline => false; 17 | 18 | public abstract bool IsBorderSupported { get; } 19 | 20 | protected BasePathProvider() 21 | { 22 | _shape = new Rect(); 23 | 24 | Invalidate(); 25 | } 26 | 27 | public void Invalidate() 28 | { 29 | IsPathDirty = true; 30 | IsBorderPathDirty = true; 31 | } 32 | 33 | public CGPath CreatePath(CGRect bounds) 34 | { 35 | /* If the path is not dirty return it */ 36 | if (!IsPathDirty || !(_shape is TShape tShape)) return Path; 37 | 38 | CreatePath(tShape, bounds); 39 | 40 | IsPathDirty = false; 41 | 42 | return Path; 43 | } 44 | 45 | public CGPath CreateBorderedPath(CGRect bounds) 46 | { 47 | /* If the path provider, does not support border, use the default */ 48 | if (!IsBorderSupported) return CreatePath(bounds); 49 | 50 | /* If the path is not dirty return it */ 51 | if (!IsBorderPathDirty || !(_shape is TShape tShape)) return BorderPath; 52 | 53 | /* If there is no need to create border, return the normal path */ 54 | if (!tShape.NeedsBorderInset) return CreatePath(bounds); 55 | 56 | CreateBorderedPath(tShape, bounds, tShape.BorderWidth); 57 | 58 | IsBorderPathDirty = false; 59 | 60 | return BorderPath; 61 | } 62 | 63 | public virtual void SetShape(IBackgroundShape shape) 64 | { 65 | _shape = shape; 66 | 67 | Invalidate(); 68 | } 69 | 70 | public abstract void CreatePath(TShape shape, CGRect bounds); 71 | 72 | public virtual void CreateBorderedPath(TShape shape, CGRect bounds, double strokeWidth) { } 73 | 74 | public void Dispose() => Dispose(true); 75 | 76 | public virtual void Dispose(bool disposing) 77 | { 78 | if (_disposed) return; 79 | 80 | _disposed = true; 81 | 82 | _shape = null; 83 | 84 | if (Path != null) 85 | { 86 | Path.Dispose(); 87 | Path = null; 88 | } 89 | 90 | if (BorderPath != null) 91 | { 92 | BorderPath.Dispose(); 93 | BorderPath = null; 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/PathProviders/CirclePathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CoreGraphics; 3 | using UIKit; 4 | using XamarinBackgroundKit.Shapes; 5 | 6 | namespace XamarinBackgroundKit.iOS.PathProviders 7 | { 8 | public class CirclePathProvider : BasePathProvider 9 | { 10 | public override bool IsBorderSupported => true; 11 | 12 | public override void CreatePath(Circle shape, CGRect bounds) 13 | { 14 | using (var bezierPath = GetCirclePath(bounds)) 15 | { 16 | Path = bezierPath.CGPath; 17 | } 18 | } 19 | 20 | public override void CreateBorderedPath(Circle shape, CGRect bounds, double strokeWidth) 21 | { 22 | using (var bezierPath = GetCirclePath(bounds, (float)strokeWidth)) 23 | { 24 | BorderPath = bezierPath.CGPath; 25 | } 26 | } 27 | 28 | private static UIBezierPath GetCirclePath(CGRect bounds, float borderWidth = 0f) 29 | { 30 | var startX = bounds.Left; 31 | var endX = bounds.Right; 32 | var startY = bounds.Top; 33 | var endY = bounds.Bottom; 34 | 35 | var delta = (float)Math.Abs(bounds.Width - bounds.Height) / 2f; 36 | 37 | if (bounds.Width > bounds.Height) 38 | { 39 | startX += delta; 40 | endX -= 2 * delta; 41 | } 42 | else if (bounds.Width < bounds.Height) 43 | { 44 | startY += delta; 45 | endY -= 2 * delta; 46 | } 47 | 48 | var croppedBounds = new CGRect( 49 | startX, startY, endX, endY); 50 | 51 | var strokedCroppedBounds = croppedBounds.Inset( 52 | borderWidth, borderWidth); 53 | 54 | var radius = ((float)Math.Min(bounds.Width, bounds.Height) - borderWidth) / 2; 55 | 56 | return UIBezierPath.FromRoundedRect(strokedCroppedBounds, radius); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/PathProviders/CornerClipPathProvider.cs: -------------------------------------------------------------------------------- 1 | using CoreGraphics; 2 | using UIKit; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.iOS.PathProviders 6 | { 7 | public class CornerClipPathProvider : BasePathProvider 8 | { 9 | public override bool IsBorderSupported => false; 10 | 11 | public override void CreatePath(CornerClip shape, CGRect bounds) 12 | { 13 | using (var bezierPath = new UIBezierPath()) 14 | { 15 | var topLeftClipSize = (float)shape.ClipSize.TopLeft; 16 | var topRightClipSize = (float)shape.ClipSize.TopRight; 17 | var bottomLeftClipSize = (int)shape.ClipSize.BottomLeft; 18 | var bottomRightClipSize = (int)shape.ClipSize.BottomRight; 19 | 20 | bezierPath.MoveTo(new CGPoint(bounds.X + topLeftClipSize, bounds.Y)); 21 | bezierPath.AddLineTo(new CGPoint(bounds.Width - topRightClipSize, bounds.Y)); 22 | bezierPath.AddLineTo(new CGPoint(bounds.Width, bounds.X + topRightClipSize)); 23 | bezierPath.AddLineTo(new CGPoint(bounds.Width, bounds.Height - bottomRightClipSize)); 24 | bezierPath.AddLineTo(new CGPoint(bounds.Width - bottomRightClipSize, bounds.Height)); 25 | bezierPath.AddLineTo(new CGPoint(bounds.X + bottomLeftClipSize, bounds.Height)); 26 | bezierPath.AddLineTo(new CGPoint(bounds.X, bounds.Height - bottomLeftClipSize)); 27 | bezierPath.AddLineTo(new CGPoint(bounds.X, bounds.Y + topLeftClipSize)); 28 | bezierPath.AddLineTo(new CGPoint(bounds.X + topLeftClipSize, bounds.Y)); 29 | bezierPath.ClosePath(); 30 | 31 | Path = bezierPath.CGPath; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/PathProviders/DiagonalPathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CoreGraphics; 3 | using UIKit; 4 | using XamarinBackgroundKit.Shapes; 5 | 6 | namespace XamarinBackgroundKit.iOS.PathProviders 7 | { 8 | public class DiagonalPathProvider : BasePathProvider 9 | { 10 | public override bool IsBorderSupported => false; 11 | 12 | public override void CreatePath(Diagonal shape, CGRect bounds) 13 | { 14 | var angleAbs = Math.Abs(shape.Angle); 15 | var isDirLeft = shape.Direction == ShapeDirection.Left; 16 | var diagonalHeight = (float)(bounds.Width * Math.Tan(Math.PI / 180 * angleAbs)); 17 | 18 | using (var bezierPath = new UIBezierPath()) 19 | { 20 | switch (shape.Position) 21 | { 22 | case ShapePosition.Left: 23 | if (isDirLeft) 24 | { 25 | bezierPath.MoveTo(new CGPoint(diagonalHeight, 0)); 26 | bezierPath.AddLineTo(new CGPoint(bounds.Width, 0)); 27 | bezierPath.AddLineTo(new CGPoint(bounds.Width, bounds.Height)); 28 | bezierPath.AddLineTo(new CGPoint(0, bounds.Height)); 29 | } 30 | else 31 | { 32 | bezierPath.MoveTo(new CGPoint(0, 0)); 33 | bezierPath.AddLineTo(new CGPoint(bounds.Width, 0)); 34 | bezierPath.AddLineTo(new CGPoint(bounds.Width, bounds.Height)); 35 | bezierPath.AddLineTo(new CGPoint(diagonalHeight, bounds.Height)); 36 | } 37 | break; 38 | case ShapePosition.Top: 39 | if (isDirLeft) 40 | { 41 | bezierPath.MoveTo(new CGPoint(bounds.Width, bounds.Height)); 42 | bezierPath.AddLineTo(new CGPoint(bounds.Width, diagonalHeight)); 43 | bezierPath.AddLineTo(new CGPoint(0, 0)); 44 | bezierPath.AddLineTo(new CGPoint(0, bounds.Height)); 45 | } 46 | else 47 | { 48 | bezierPath.MoveTo(new CGPoint(bounds.Width, bounds.Height)); 49 | bezierPath.AddLineTo(new CGPoint(bounds.Width, 0)); 50 | bezierPath.AddLineTo(new CGPoint(0, diagonalHeight)); 51 | bezierPath.AddLineTo(new CGPoint(0, bounds.Height)); 52 | } 53 | break; 54 | case ShapePosition.Bottom: 55 | if (isDirLeft) 56 | { 57 | bezierPath.MoveTo(new CGPoint(0, 0)); 58 | bezierPath.AddLineTo(new CGPoint(bounds.Width, 0)); 59 | bezierPath.AddLineTo(new CGPoint(bounds.Width, bounds.Height - diagonalHeight)); 60 | bezierPath.AddLineTo(new CGPoint(0, bounds.Height)); 61 | } 62 | else 63 | { 64 | bezierPath.MoveTo(new CGPoint(bounds.Width, bounds.Height)); 65 | bezierPath.AddLineTo(new CGPoint(0, bounds.Height - diagonalHeight)); 66 | bezierPath.AddLineTo(new CGPoint(0, 0)); 67 | bezierPath.AddLineTo(new CGPoint(bounds.Width, 0)); 68 | } 69 | break; 70 | case ShapePosition.Right: 71 | if (isDirLeft) 72 | { 73 | bezierPath.MoveTo(new CGPoint(0, 0)); 74 | bezierPath.AddLineTo(new CGPoint(bounds.Width, 0)); 75 | bezierPath.AddLineTo(new CGPoint(bounds.Width - diagonalHeight, bounds.Height)); 76 | bezierPath.AddLineTo(new CGPoint(0, bounds.Height)); 77 | } 78 | else 79 | { 80 | bezierPath.MoveTo(new CGPoint(0, 0)); 81 | bezierPath.AddLineTo(new CGPoint(bounds.Width - diagonalHeight, 0)); 82 | bezierPath.AddLineTo(new CGPoint(bounds.Width, bounds.Height)); 83 | bezierPath.AddLineTo(new CGPoint(0, bounds.Height)); 84 | } 85 | break; 86 | } 87 | 88 | bezierPath.ClosePath(); 89 | 90 | Path = bezierPath.CGPath; 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/PathProviders/IPathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CoreGraphics; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.iOS.PathProviders 6 | { 7 | public interface IPathProvider : IDisposable 8 | { 9 | CGPath Path { get; } 10 | bool IsPathDirty { get; } 11 | bool IsBorderPathDirty { get; } 12 | bool IsBorderSupported { get; } 13 | bool CanHandledByOutline { get; } 14 | 15 | void Invalidate(); 16 | void SetShape(IBackgroundShape shape); 17 | 18 | CGPath CreatePath(CGRect bounds); 19 | CGPath CreateBorderedPath(CGRect bounds); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/PathProviders/PathProvidersContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.iOS.PathProviders 6 | { 7 | public static class PathProvidersContainer 8 | { 9 | private static bool _isInitialized; 10 | 11 | private static readonly Lazy>> FactoriesLazy = 12 | new Lazy>>(() => new Dictionary>()); 13 | 14 | private static Dictionary> Factories => FactoriesLazy.Value; 15 | 16 | public static void Init() 17 | { 18 | _isInitialized = true; 19 | 20 | Register(() => new ArcPathProvider()); 21 | Register(() => new RectPathProvider()); 22 | Register(() => new CirclePathProvider()); 23 | Register(() => new DiagonalPathProvider()); 24 | Register(() => new TrianglePathProvider()); 25 | Register(() => new RoundRectPathProvider()); 26 | Register(() => new CornerClipPathProvider()); 27 | } 28 | 29 | public static IPathProvider Resolve() where TShape : IBackgroundShape 30 | { 31 | return Resolve(typeof(TShape)); 32 | } 33 | 34 | public static IPathProvider Resolve(Type shapeType) 35 | { 36 | if (!_isInitialized) 37 | { 38 | Init(); 39 | } 40 | 41 | if (!Factories.ContainsKey(shapeType)) 42 | throw new Exception("Not found registered PathProvider"); 43 | 44 | return Factories[shapeType](); 45 | } 46 | 47 | public static void Register(Func pathProviderFactory) where TShape : IBackgroundShape 48 | { 49 | if (Factories.ContainsKey(typeof(TShape))) 50 | { 51 | Factories[typeof(TShape)] = pathProviderFactory; 52 | return; 53 | } 54 | 55 | Factories.Add(typeof(TShape), pathProviderFactory); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/PathProviders/RectPathProvider.cs: -------------------------------------------------------------------------------- 1 | using CoreGraphics; 2 | using UIKit; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.iOS.PathProviders 6 | { 7 | public class RectPathProvider : BasePathProvider 8 | { 9 | public override bool IsBorderSupported => true; 10 | 11 | public override void CreatePath(Rect shape, CGRect bounds) 12 | { 13 | using (var bezierPath = UIBezierPath.FromRect(bounds)) 14 | { 15 | Path = bezierPath.CGPath; 16 | } 17 | } 18 | 19 | public override void CreateBorderedPath(Rect shape, CGRect bounds, double strokeWidth) 20 | { 21 | using (var bezierPath = UIBezierPath.FromRect(bounds.Inset((float)strokeWidth, (float)strokeWidth))) 22 | { 23 | BorderPath = bezierPath.CGPath; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/PathProviders/RoundRectPathProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CoreGraphics; 3 | using UIKit; 4 | using Xamarin.Forms; 5 | using XamarinBackgroundKit.Extensions; 6 | using XamarinBackgroundKit.Shapes; 7 | 8 | namespace XamarinBackgroundKit.iOS.PathProviders 9 | { 10 | public class RoundRectPathProvider : BasePathProvider 11 | { 12 | public override bool IsBorderSupported => true; 13 | 14 | public override void CreatePath(RoundRect shape, CGRect bounds) 15 | { 16 | using (var bezierPath = GetRoundCornersPath(bounds, shape.CornerRadius)) 17 | { 18 | Path = bezierPath.CGPath; 19 | } 20 | } 21 | 22 | public override void CreateBorderedPath(RoundRect shape, CGRect bounds, double strokeWidth) 23 | { 24 | var strokeWidthF = (float)strokeWidth; 25 | var insetBounds = bounds.Inset(strokeWidthF, strokeWidthF); 26 | 27 | using (var bezierPath = GetRoundCornersPath(insetBounds, shape.CornerRadius, strokeWidthF)) 28 | { 29 | BorderPath = bezierPath.CGPath; 30 | } 31 | } 32 | 33 | private static UIBezierPath GetRoundCornersPath(CGRect bounds, CornerRadius cornerRadius, float borderWidth = 0f) 34 | { 35 | if (cornerRadius.IsEmpty()) 36 | { 37 | return UIBezierPath.FromRect(bounds); 38 | } 39 | 40 | if (cornerRadius.IsAllRadius()) 41 | { 42 | return UIBezierPath.FromRoundedRect(bounds, InsetCorner(cornerRadius.TopLeft, borderWidth)); 43 | } 44 | 45 | var topLeft = InsetCorner(cornerRadius.TopLeft, borderWidth); 46 | var topRight = InsetCorner(cornerRadius.TopRight, borderWidth); 47 | var bottomLeft = InsetCorner(cornerRadius.BottomLeft, borderWidth); 48 | var bottomRight = InsetCorner(cornerRadius.BottomRight, borderWidth); 49 | 50 | var bezierPath = new UIBezierPath(); 51 | bezierPath.AddArc(new CGPoint((float)bounds.X + bounds.Width - topRight, (float)bounds.Y + topRight), topRight, (float)(Math.PI * 1.5), (float)Math.PI * 2, true); 52 | bezierPath.AddArc(new CGPoint((float)bounds.X + bounds.Width - bottomRight, (float)bounds.Y + bounds.Height - bottomRight), bottomRight, 0, (float)(Math.PI * .5), true); 53 | bezierPath.AddArc(new CGPoint((float)bounds.X + bottomLeft, (float)bounds.Y + bounds.Height - bottomLeft), bottomLeft, (float)(Math.PI * .5), (float)Math.PI, true); 54 | bezierPath.AddArc(new CGPoint((float)bounds.X + topLeft, (float)bounds.Y + topLeft), topLeft, (float)Math.PI, (float)(Math.PI * 1.5), true); 55 | bezierPath.ClosePath(); 56 | 57 | return bezierPath; 58 | } 59 | 60 | private static float InsetCorner(double corner, float borderWidth) 61 | { 62 | var temp = corner - borderWidth; 63 | return temp < 0 ? 0 : (float)temp; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/PathProviders/TrianglePathProvider.cs: -------------------------------------------------------------------------------- 1 | using CoreGraphics; 2 | using UIKit; 3 | using Xamarin.Forms; 4 | using XamarinBackgroundKit.Shapes; 5 | 6 | namespace XamarinBackgroundKit.iOS.PathProviders 7 | { 8 | public class TrianglePathProvider : BasePathProvider 9 | { 10 | public override bool IsBorderSupported => false; 11 | 12 | public override void CreatePath(Triangle shape, CGRect bounds) 13 | { 14 | using (var bezierPath = new UIBezierPath()) 15 | { 16 | bezierPath.MoveTo(shape.PointA.ToCGPointProp(bounds)); 17 | bezierPath.AddLineTo(shape.PointB.ToCGPointProp(bounds)); 18 | bezierPath.AddLineTo(shape.PointC.ToCGPointProp(bounds)); 19 | bezierPath.ClosePath(); 20 | 21 | Path = bezierPath.CGPath; 22 | } 23 | } 24 | } 25 | 26 | internal static class PointExtensions 27 | { 28 | public static CGPoint ToCGPointProp(this Point point, CGRect bounds) 29 | { 30 | return new CGPoint(point.X * bounds.Width, point.Y * bounds.Height); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using Xamarin.Forms; 4 | 5 | [assembly: AssemblyTitle("XamarinBackgroundKit.iOS")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("XamarinBackgroundKit.iOS")] 10 | [assembly: AssemblyCopyright("Copyright © 2017")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("50c7b8c9-e664-45af-b88e-0c9b8b9c1be1")] 17 | 18 | [assembly: AssemblyVersion("1.0.0.0")] 19 | [assembly: AssemblyFileVersion("1.0.0.0")] 20 | 21 | [assembly: ResolutionGroupName("XamarinBackgroundKit")] 22 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/Renderers/MaterialContentViewRenderer.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Foundation; 3 | using UIKit; 4 | using Xamarin.Forms; 5 | using Xamarin.Forms.Platform.iOS; 6 | using XamarinBackgroundKit.Controls; 7 | using XamarinBackgroundKit.iOS.Renderers; 8 | 9 | [assembly: ExportRenderer(typeof(MaterialContentView), typeof(MaterialContentViewRenderer))] 10 | namespace XamarinBackgroundKit.iOS.Renderers 11 | { 12 | public class MaterialContentViewRenderer : ViewRenderer 13 | { 14 | private bool _disposed; 15 | protected MaterialBackgroundManager BackgroundManager; 16 | 17 | private MaterialContentView ElementController => Element as MaterialContentView; 18 | 19 | public override void LayoutSubviews() 20 | { 21 | base.LayoutSubviews(); 22 | 23 | BackgroundManager?.InvalidateLayer(); 24 | } 25 | 26 | #region Element Changed 27 | 28 | protected override void OnElementChanged(ElementChangedEventArgs e) 29 | { 30 | base.OnElementChanged(e); 31 | 32 | if (e.NewElement == null) return; 33 | 34 | if (BackgroundManager == null) 35 | { 36 | BackgroundManager = new MaterialBackgroundManager(this); 37 | } 38 | 39 | UpdateIsFocusable(); 40 | } 41 | 42 | #endregion 43 | 44 | #region Property Changed 45 | 46 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) 47 | { 48 | if (_disposed) return; 49 | 50 | base.OnElementPropertyChanged(sender, e); 51 | 52 | if (e.PropertyName == MaterialContentView.IsFocusableProperty.PropertyName 53 | || e.PropertyName == MaterialContentView.IsClickableProperty.PropertyName) UpdateIsFocusable(); 54 | } 55 | 56 | private void UpdateIsFocusable() 57 | { 58 | if (ElementController == null) return; 59 | 60 | if (ElementController.IsFocusable && ElementController.IsClickable) 61 | { 62 | //MultipleTouchEnabled = true; 63 | UserInteractionEnabled = true; 64 | } 65 | else 66 | { 67 | //MultipleTouchEnabled = false; 68 | UserInteractionEnabled = false; 69 | } 70 | } 71 | 72 | #endregion 73 | 74 | #region Touch Handling 75 | 76 | public override void TouchesBegan(NSSet touches, UIEvent evt) 77 | { 78 | base.TouchesBegan(touches, evt); 79 | 80 | if (ElementController == null) return; 81 | 82 | if (ElementController.IsFocusable) 83 | { 84 | ElementController.OnPressed(); 85 | } 86 | } 87 | 88 | public override void TouchesEnded(NSSet touches, UIEvent evt) 89 | { 90 | base.TouchesEnded(touches, evt); 91 | 92 | if (ElementController == null) return; 93 | 94 | if (ElementController.IsClickable) 95 | { 96 | ElementController.OnClicked(); 97 | } 98 | 99 | if (ElementController.IsFocusable) 100 | { 101 | ElementController.OnReleased(); 102 | ElementController.OnReleasedOrCancelled(); 103 | } 104 | } 105 | 106 | public override void TouchesCancelled(NSSet touches, UIEvent evt) 107 | { 108 | base.TouchesCancelled(touches, evt); 109 | 110 | if (ElementController == null) return; 111 | 112 | if (ElementController.IsFocusable) 113 | { 114 | ElementController.OnCancelled(); 115 | ElementController.OnReleasedOrCancelled(); 116 | } 117 | } 118 | 119 | #endregion 120 | 121 | #region LifeCycle 122 | 123 | protected override void Dispose(bool disposing) 124 | { 125 | if (_disposed) return; 126 | 127 | _disposed = true; 128 | 129 | if (disposing) 130 | { 131 | if (BackgroundManager != null) 132 | { 133 | BackgroundManager.Dispose(); 134 | BackgroundManager = null; 135 | } 136 | } 137 | 138 | base.Dispose(disposing); 139 | } 140 | 141 | #endregion 142 | } 143 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/Renderers/MaterialShapeViewRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using Xamarin.Forms; 4 | using Xamarin.Forms.Platform.iOS; 5 | using XamarinBackgroundKit.Controls; 6 | using XamarinBackgroundKit.iOS.Renderers; 7 | 8 | [assembly: ExportRenderer(typeof(MaterialShapeView), typeof(MaterialShapeViewRenderer))] 9 | namespace XamarinBackgroundKit.iOS.Renderers 10 | { 11 | public class MaterialShapeViewRenderer : MaterialContentViewRenderer 12 | { 13 | private bool _disposed; 14 | 15 | private MaterialShapeView ElementController => Element as MaterialShapeView; 16 | 17 | protected override void OnElementChanged(ElementChangedEventArgs e) 18 | { 19 | base.OnElementChanged(e); 20 | 21 | UpdateShape(); 22 | } 23 | 24 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) 25 | { 26 | base.OnElementPropertyChanged(sender, e); 27 | 28 | if (e.PropertyName == MaterialShapeView.ShapeProperty.PropertyName) UpdateShape(); 29 | } 30 | 31 | private void OnShapeInvalidateRequested(object sender, EventArgs e) => UpdateShape(); 32 | 33 | private void UpdateShape() 34 | { 35 | if (_disposed) return; 36 | 37 | BackgroundManager?.SetShape(ElementController.Shape); 38 | 39 | SetNeedsLayout(); 40 | } 41 | 42 | protected override void Dispose(bool disposing) 43 | { 44 | if (_disposed) return; 45 | 46 | _disposed = true; 47 | 48 | base.Dispose(disposing); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKit.iOS/XamarinBackgroundKit.iOS.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {E71F3053-056C-4381-9638-048ED73BDFF6} 9 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10 | {a52b8a63-bc84-4b47-910d-692533484892} 11 | Library 12 | XamarinBackgroundKit.iOS 13 | Resources 14 | XamarinBackgroundKit.iOS 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug 21 | DEBUG; 22 | prompt 23 | 4 24 | false 25 | 26 | 27 | full 28 | true 29 | bin\Release 30 | prompt 31 | 4 32 | false 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 1.2.0 70 | 71 | 72 | 92.0.0 73 | 74 | 75 | 4.6.0.1180 76 | 77 | 78 | 79 | 80 | {54366595-A90D-4AC0-B816-FCE69FA6410F} 81 | XamarinBackgroundKit 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/IBackgroundElement.cs: -------------------------------------------------------------------------------- 1 | using XamarinBackgroundKit.Controls; 2 | 3 | namespace XamarinBackgroundKit.Abstractions 4 | { 5 | public interface IBackgroundElement 6 | { 7 | Background Background { get; } 8 | 9 | void OnBackgroundChanged(Background oldValue, Background newValue); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/IBackgroundShape.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xamarin.Forms; 3 | 4 | namespace XamarinBackgroundKit.Shapes 5 | { 6 | public interface IBackgroundShape 7 | { 8 | double BorderWidth { get; } 9 | bool NeedsBorderInset { get; } 10 | 11 | event EventHandler ShapeInvalidateRequested; 12 | 13 | void SetParent(VisualElement parent); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/IBorderElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Controls; 3 | 4 | namespace XamarinBackgroundKit.Abstractions 5 | { 6 | public interface IBorderElement 7 | { 8 | Color BorderColor { get; } 9 | double BorderWidth { get; } 10 | BorderStyle BorderStyle { get; } 11 | 12 | double DashGap { get; } 13 | double DashWidth { get; } 14 | GradientBrush BorderGradientBrush { get; } 15 | 16 | void OnBorderColorPropertyChanged(Color oldValue, Color newValue); 17 | void OnBorderWidthPropertyChanged(double oldValue, double newValue); 18 | void OnBorderStylePropertyChanged(BorderStyle oldValue, BorderStyle newValue); 19 | void OnDashGapPropertyChanged(double oldValue, double newValue); 20 | void OnDashWidthPropertyChanged(double oldValue, double newValue); 21 | void OnBorderGradientBrushPropertyChanged(GradientBrush oldValue, GradientBrush newValue); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/IClickableElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | using Xamarin.Forms; 4 | 5 | namespace XamarinBackgroundKit.Abstractions 6 | { 7 | public interface IClickableElement 8 | { 9 | event EventHandler Clicked; 10 | 11 | bool IsClickable { get; } 12 | 13 | ICommand ClickedCommand { get; } 14 | 15 | object ClickedCommandParameter { get; } 16 | 17 | void OnClicked(); 18 | 19 | void OnIsClickablePropertyChanged(bool oldValue, bool newValue); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/ICornerElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Abstractions 4 | { 5 | public interface ICornerElement 6 | { 7 | CornerRadius CornerRadius { get; } 8 | 9 | void OnCornerRadiusPropertyChanged(CornerRadius oldValue, CornerRadius newValue); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/IElevationElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Abstractions 4 | { 5 | public interface IElevationElement 6 | { 7 | double Elevation { get; } 8 | 9 | double TranslationZ { get; } 10 | 11 | Color ShadowColor { get; } 12 | 13 | void OnElevationPropertyChanged(double oldValue, double newValue); 14 | 15 | void OnTranslationZPropertyChanged(double oldValue, double newValue); 16 | 17 | void OnShadowColorPropertyChanged(Color oldValue, Color newValue); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/IFocusableElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | using Xamarin.Forms; 4 | 5 | namespace XamarinBackgroundKit.Abstractions 6 | { 7 | public interface IFocusableElement 8 | { 9 | event EventHandler Pressed; 10 | event EventHandler Released; 11 | event EventHandler Cancelled; 12 | event EventHandler ReleasedOrCancelled; 13 | 14 | bool IsFocusable { get; } 15 | 16 | ICommand PressedCommand { get; } 17 | ICommand ReleasedCommand { get; } 18 | ICommand CancelledCommand { get; } 19 | ICommand ReleasedOrCancelledCommand { get; } 20 | 21 | object PressedCommandParameter { get; } 22 | object ReleasedCommandParameter { get; } 23 | object CancelledCommandParameter { get; } 24 | object ReleasedOrCancelledCommandParameter { get; } 25 | 26 | void OnPressed(); 27 | void OnReleased(); 28 | void OnCancelled(); 29 | void OnReleasedOrCancelled(); 30 | 31 | void OnIsFocusablePropertyChanged(bool oldValue, bool newValue); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/IFontElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Abstractions 4 | { 5 | public interface IFontElement 6 | { 7 | FontAttributes FontAttributes { get; } 8 | string FontFamily { get; } 9 | 10 | [System.ComponentModel.TypeConverter(typeof(FontSizeConverter))] 11 | double FontSize { get; } 12 | 13 | Font Font { get; } 14 | 15 | void OnFontFamilyChanged(string oldValue, string newValue); 16 | void OnFontSizeChanged(double oldValue, double newValue); 17 | double FontSizeDefaultValueCreator(); 18 | void OnFontAttributesChanged(FontAttributes oldValue, FontAttributes newValue); 19 | void OnFontChanged(Font oldValue, Font newValue); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/IGradientElement.cs: -------------------------------------------------------------------------------- 1 | using XamarinBackgroundKit.Controls; 2 | 3 | namespace XamarinBackgroundKit.Abstractions 4 | { 5 | public interface IGradientElement 6 | { 7 | GradientBrush GradientBrush { get; } 8 | 9 | void OnGradientBrushPropertyChanged(GradientBrush oldValue, GradientBrush newValue); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/IMaterialVisualElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using Xamarin.Forms; 4 | 5 | namespace XamarinBackgroundKit.Abstractions 6 | { 7 | public interface IMaterialVisualElement : INotifyPropertyChanged, IBorderElement, ICornerElement, IGradientElement, IElevationElement 8 | { 9 | Color Color { get; } 10 | 11 | bool IsRippleEnabled { get; } 12 | 13 | Color RippleColor { get; } 14 | 15 | event EventHandler InvalidateGradientRequested; 16 | 17 | event EventHandler InvalidateBorderGradientRequested; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Abstractions/ITextElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Abstractions 4 | { 5 | public interface ITextElement 6 | { 7 | string Text { get; } 8 | Color TextColor { get; } 9 | 10 | void OnTextPropertyChanged(string oldValue, string newValue); 11 | void OnTextColorPropertyChanged(Color oldValue, Color newValue); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Base/BackgroundElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Abstractions; 3 | 4 | namespace XamarinBackgroundKit.Controls.Base 5 | { 6 | public static class BackgroundElement 7 | { 8 | public static readonly BindableProperty BackgroundProperty = BindableProperty.Create( 9 | nameof(IBackgroundElement.Background), typeof(Background), typeof(IBackgroundElement), 10 | defaultValueCreator: b => new Background(), propertyChanged: OnBackgroundPropertyChanged); 11 | 12 | private static void OnBackgroundPropertyChanged(BindableObject bindable, object oldValue, object newValue) 13 | { 14 | ((IBackgroundElement)bindable).OnBackgroundChanged((Background)oldValue, (Background)newValue); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Base/BorderElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using IBorderElement = XamarinBackgroundKit.Abstractions.IBorderElement; 3 | 4 | namespace XamarinBackgroundKit.Controls.Base 5 | { 6 | public static class BorderElement 7 | { 8 | public static readonly BindableProperty BorderColorProperty = BindableProperty.Create( 9 | nameof(IBorderElement.BorderColor), typeof(Color), typeof(IBorderElement), Color.Default, 10 | propertyChanged: OnBorderColorPropertyChanged); 11 | 12 | public static readonly BindableProperty BorderWidthProperty = BindableProperty.Create( 13 | nameof(IBorderElement.BorderWidth), typeof(double), typeof(IBorderElement), 0d, 14 | propertyChanged: OnBorderWidthPropertyChanged); 15 | 16 | public static readonly BindableProperty BorderStyleProperty = BindableProperty.Create( 17 | nameof(IBorderElement.BorderStyle), typeof(BorderStyle), typeof(IBorderElement), BorderStyle.Inner, 18 | propertyChanged: OnBorderStylePropertyChanged); 19 | 20 | public static readonly BindableProperty DashGapProperty = BindableProperty.Create( 21 | nameof(IBorderElement.DashGap), typeof(double), typeof(IBorderElement), 0d, 22 | propertyChanged: OnDashGapPropertyChanged); 23 | 24 | public static readonly BindableProperty DashWidthProperty = BindableProperty.Create( 25 | nameof(IBorderElement.DashWidth), typeof(double), typeof(IBorderElement), 0d, 26 | propertyChanged: OnDashWidthPropertyChanged); 27 | 28 | public static readonly BindableProperty BorderGradientBrushProperty = BindableProperty.Create( 29 | nameof(IBorderElement.BorderGradientBrush), typeof(LinearGradientBrush), typeof(IBorderElement), new LinearGradientBrush(), 30 | propertyChanged: OnBorderGradientBrushPropertyChanged, 31 | defaultValueCreator: b => new LinearGradientBrush()); 32 | 33 | private static void OnBorderColorPropertyChanged(BindableObject bindable, object oldValue, object newValue) 34 | { 35 | ((IBorderElement)bindable).OnBorderColorPropertyChanged((Color)oldValue, (Color)newValue); 36 | } 37 | 38 | private static void OnBorderWidthPropertyChanged(BindableObject bindable, object oldValue, object newValue) 39 | { 40 | ((IBorderElement)bindable).OnBorderWidthPropertyChanged((double)oldValue, (double)newValue); 41 | } 42 | 43 | private static void OnBorderStylePropertyChanged(BindableObject bindable, object oldValue, object newValue) 44 | { 45 | ((IBorderElement)bindable).OnBorderStylePropertyChanged((BorderStyle)oldValue, (BorderStyle)newValue); 46 | } 47 | 48 | private static void OnDashGapPropertyChanged(BindableObject bindable, object oldValue, object newValue) 49 | { 50 | ((IBorderElement)bindable).OnDashGapPropertyChanged((double)oldValue, (double)newValue); 51 | } 52 | 53 | private static void OnDashWidthPropertyChanged(BindableObject bindable, object oldValue, object newValue) 54 | { 55 | ((IBorderElement)bindable).OnDashWidthPropertyChanged((double)oldValue, (double)newValue); 56 | } 57 | 58 | private static void OnBorderGradientBrushPropertyChanged(BindableObject bindable, object oldValue, object newValue) 59 | { 60 | ((IBorderElement)bindable).OnBorderGradientBrushPropertyChanged((LinearGradientBrush)oldValue, (LinearGradientBrush)newValue); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Base/ClickableElement.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | using Xamarin.Forms; 3 | using XamarinBackgroundKit.Abstractions; 4 | 5 | namespace XamarinBackgroundKit.Controls.Base 6 | { 7 | public static class ClickableElement 8 | { 9 | public static readonly BindableProperty IsClickableProperty = BindableProperty.Create( 10 | nameof(IClickableElement.IsClickable), typeof(bool), typeof(IClickableElement), true, 11 | propertyChanged: OnIsClickablePropertyChanged); 12 | 13 | public static readonly BindableProperty ClickedCommandProperty = BindableProperty.Create( 14 | nameof(IClickableElement.ClickedCommand), typeof(ICommand), typeof(IClickableElement)); 15 | 16 | public static readonly BindableProperty ClickedCommandParameterProperty = BindableProperty.Create( 17 | nameof(IClickableElement.ClickedCommandParameter), typeof(object), typeof(IClickableElement)); 18 | 19 | private static void OnIsClickablePropertyChanged(BindableObject bindable, object oldValue, object newValue) 20 | { 21 | ((IClickableElement)bindable).OnIsClickablePropertyChanged((bool)oldValue, (bool)newValue); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Base/CornerElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Abstractions; 3 | 4 | namespace XamarinBackgroundKit.Controls.Base 5 | { 6 | public static class CornerElement 7 | { 8 | public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create( 9 | nameof(ICornerElement.CornerRadius), typeof(CornerRadius), typeof(ICornerElement), default(CornerRadius), 10 | propertyChanged: OnCornerRadiusPropertyChanged); 11 | 12 | private static void OnCornerRadiusPropertyChanged(BindableObject bindable, object oldValue, object newValue) 13 | { 14 | ((ICornerElement)bindable).OnCornerRadiusPropertyChanged((CornerRadius)oldValue, (CornerRadius)newValue); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Base/ElevationElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Abstractions; 3 | 4 | namespace XamarinBackgroundKit.Controls.Base 5 | { 6 | public static class ElevationElement 7 | { 8 | public static readonly BindableProperty ElevationProperty = BindableProperty.Create( 9 | nameof(IElevationElement.Elevation), typeof(double), typeof(IElevationElement), 0d, 10 | propertyChanged: OnElevationPropertyChanged); 11 | 12 | public static readonly BindableProperty ShadowColorProperty = BindableProperty.Create( 13 | nameof(IElevationElement.ShadowColor), typeof(Color), typeof(IElevationElement), Color.Default, 14 | propertyChanged: OnShadowColorPropertyChanged); 15 | 16 | public static readonly BindableProperty TranslationZProperty = BindableProperty.Create( 17 | nameof(IElevationElement.TranslationZ), typeof(double), typeof(IElevationElement), 0d, 18 | propertyChanged: OnTranslationZPropertyChanged); 19 | 20 | private static void OnElevationPropertyChanged(BindableObject bindable, object oldValue, object newValue) 21 | { 22 | ((IElevationElement)bindable).OnElevationPropertyChanged((double)oldValue, (double)newValue); 23 | } 24 | 25 | private static void OnShadowColorPropertyChanged(BindableObject bindable, object oldValue, object newValue) 26 | { 27 | ((IElevationElement)bindable).OnShadowColorPropertyChanged((Color)oldValue, (Color)newValue); 28 | } 29 | 30 | private static void OnTranslationZPropertyChanged(BindableObject bindable, object oldValue, object newValue) 31 | { 32 | ((IElevationElement)bindable).OnTranslationZPropertyChanged((double)oldValue, (double)newValue); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Base/FocusableElement.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | using Xamarin.Forms; 3 | using XamarinBackgroundKit.Abstractions; 4 | 5 | namespace XamarinBackgroundKit.Controls.Base 6 | { 7 | public static class FocusableElement 8 | { 9 | public static readonly BindableProperty IsFocusableProperty = BindableProperty.Create( 10 | nameof(IFocusableElement.IsFocusable), typeof(bool), typeof(IFocusableElement), true, 11 | propertyChanged: OnIsFocusablePropertyChanged); 12 | 13 | public static readonly BindableProperty PressedCommandProperty = BindableProperty.Create( 14 | nameof(IFocusableElement.PressedCommand), typeof(ICommand), typeof(IFocusableElement)); 15 | 16 | public static readonly BindableProperty PressedCommandParameterProperty = BindableProperty.Create( 17 | nameof(IFocusableElement.PressedCommandParameter), typeof(object), typeof(IFocusableElement)); 18 | 19 | public static readonly BindableProperty ReleasedCommandProperty = BindableProperty.Create( 20 | nameof(IFocusableElement.ReleasedCommand), typeof(ICommand), typeof(IFocusableElement)); 21 | 22 | public static readonly BindableProperty ReleasedCommandParameterProperty = BindableProperty.Create( 23 | nameof(IFocusableElement.ReleasedCommandParameter), typeof(object), typeof(IFocusableElement)); 24 | 25 | public static readonly BindableProperty CancelledCommandProperty = BindableProperty.Create( 26 | nameof(IFocusableElement.CancelledCommand), typeof(ICommand), typeof(IFocusableElement)); 27 | 28 | public static readonly BindableProperty CancelledCommandParameterProperty = BindableProperty.Create( 29 | nameof(IFocusableElement.CancelledCommandParameter), typeof(object), typeof(IFocusableElement)); 30 | 31 | public static readonly BindableProperty ReleasedOrCancelledCommandProperty = BindableProperty.Create( 32 | nameof(IFocusableElement.ReleasedOrCancelledCommand), typeof(ICommand), typeof(IFocusableElement)); 33 | 34 | public static readonly BindableProperty ReleasedOrCancelledCommandParameterProperty = BindableProperty.Create( 35 | nameof(IFocusableElement.ReleasedOrCancelledCommandParameter), typeof(object), typeof(IFocusableElement)); 36 | 37 | private static void OnIsFocusablePropertyChanged(BindableObject bindable, object oldValue, object newValue) 38 | { 39 | ((IFocusableElement)bindable).OnIsFocusablePropertyChanged((bool)oldValue, (bool)newValue); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Base/GradientElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Abstractions; 3 | 4 | namespace XamarinBackgroundKit.Controls.Base 5 | { 6 | public static class GradientElement 7 | { 8 | public static readonly BindableProperty GradientBrushProperty = BindableProperty.Create( 9 | nameof(IGradientElement.GradientBrush), typeof(LinearGradientBrush), typeof(IGradientElement), new LinearGradientBrush(), 10 | propertyChanged: OnGradientBrushPropertyChanged, 11 | defaultValueCreator: b => new LinearGradientBrush()); 12 | 13 | private static void OnGradientBrushPropertyChanged(BindableObject bindable, object oldValue, object newValue) 14 | { 15 | ((IGradientElement)bindable).OnGradientBrushPropertyChanged((LinearGradientBrush)oldValue, (LinearGradientBrush)newValue); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Base/TextElement.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Abstractions; 3 | 4 | namespace XamarinBackgroundKit.Controls.Base 5 | { 6 | public static class TextElement 7 | { 8 | public static readonly BindableProperty TextProperty = BindableProperty.Create( 9 | nameof(ITextElement.Text), typeof(string), typeof(ITextElement), default(string), 10 | propertyChanged: OnTextPropertyChanged); 11 | 12 | private static void OnTextPropertyChanged(BindableObject bindable, object oldValue, object newValue) 13 | { 14 | ((ITextElement)bindable).OnTextPropertyChanged((string)oldValue, (string)newValue); 15 | } 16 | 17 | public static readonly BindableProperty TextColorProperty = BindableProperty.Create( 18 | nameof(ITextElement.TextColor), typeof(Color), typeof(ITextElement), Color.Default, 19 | propertyChanged: OnTextColorPropertyChanged); 20 | 21 | private static void OnTextColorPropertyChanged(BindableObject bindable, object oldValue, object newValue) 22 | { 23 | ((ITextElement)bindable).OnTextColorPropertyChanged((Color)oldValue, (Color)newValue); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/BorderStyle.cs: -------------------------------------------------------------------------------- 1 | namespace XamarinBackgroundKit.Controls 2 | { 3 | public enum BorderStyle 4 | { 5 | Inner, 6 | Outer 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Chips/BaseMaterialChip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xamarin.Forms; 3 | using XamarinBackgroundKit.Abstractions; 4 | using XamarinBackgroundKit.Controls.Base; 5 | 6 | namespace XamarinBackgroundKit.Controls.Chips 7 | { 8 | public class BaseMaterialChip : MaterialContentView, IFontElement, ITextElement 9 | { 10 | #region Bindable Properties 11 | 12 | #region ITextElement Properties 13 | 14 | public static readonly BindableProperty TextProperty = TextElement.TextProperty; 15 | 16 | public string Text 17 | { 18 | get => (string)GetValue(TextProperty); 19 | set => SetValue(TextProperty, value); 20 | } 21 | 22 | public static readonly BindableProperty TextColorProperty = TextElement.TextColorProperty; 23 | 24 | public Color TextColor 25 | { 26 | get => (Color)GetValue(TextColorProperty); 27 | set => SetValue(TextColorProperty, value); 28 | } 29 | 30 | #endregion 31 | 32 | #region IFontElement Properties 33 | 34 | public static readonly BindableProperty FontFamilyProperty = FontElement.FontFamilyProperty; 35 | 36 | public string FontFamily 37 | { 38 | get => (string)GetValue(FontFamilyProperty); 39 | set => SetValue(FontFamilyProperty, value); 40 | } 41 | 42 | public static readonly BindableProperty FontSizeProperty = FontElement.FontSizeProperty; 43 | 44 | [System.ComponentModel.TypeConverter(typeof(FontSizeConverter))] 45 | public double FontSize 46 | { 47 | get => (double)GetValue(FontSizeProperty); 48 | set => SetValue(FontSizeProperty, value); 49 | } 50 | 51 | public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty; 52 | 53 | public FontAttributes FontAttributes 54 | { 55 | get => (FontAttributes)GetValue(FontAttributesProperty); 56 | set => SetValue(FontAttributesProperty, value); 57 | } 58 | 59 | public static readonly BindableProperty FontProperty = FontElement.FontProperty; 60 | 61 | [Obsolete("Font is obsolete as of version 1.3.0. Please use the Font attributes which are on the class itself.")] 62 | public Font Font 63 | { 64 | get => (Font)GetValue(FontProperty); 65 | set => SetValue(FontProperty, value); 66 | } 67 | 68 | #endregion 69 | 70 | #endregion 71 | 72 | #region IFontElement Implementation 73 | 74 | double IFontElement.FontSizeDefaultValueCreator() => 75 | Device.GetNamedSize(NamedSize.Default, this); 76 | 77 | void IFontElement.OnFontAttributesChanged(FontAttributes oldValue, FontAttributes newValue) => 78 | InvalidateMeasure(); 79 | 80 | void IFontElement.OnFontFamilyChanged(string oldValue, string newValue) => 81 | InvalidateMeasure(); 82 | 83 | void IFontElement.OnFontSizeChanged(double oldValue, double newValue) => 84 | InvalidateMeasure(); 85 | 86 | void IFontElement.OnFontChanged(Font oldValue, Font newValue) => 87 | InvalidateMeasure(); 88 | 89 | #endregion 90 | 91 | #region ITextElement Implementation 92 | 93 | void ITextElement.OnTextPropertyChanged(string oldValue, string newValue) => 94 | InvalidateMeasure(); 95 | 96 | void ITextElement.OnTextColorPropertyChanged(Color oldValue, Color newValue) { } 97 | 98 | #endregion 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Chips/MaterialButtonChip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xamarin.Forms; 3 | 4 | namespace XamarinBackgroundKit.Controls.Chips 5 | { 6 | public class MaterialButtonChip : BaseMaterialChip 7 | { 8 | private readonly Button _button; 9 | 10 | public MaterialButtonChip() 11 | { 12 | _button = new Button 13 | { 14 | Text = Text, 15 | TextColor = TextColor, 16 | FontSize = FontSize, 17 | FontFamily = FontFamily, 18 | BorderColor = Color.Transparent, 19 | BackgroundColor = Color.Transparent, 20 | VerticalOptions = LayoutOptions.Center, 21 | HorizontalOptions = LayoutOptions.Center 22 | }; 23 | 24 | _button.Clicked += OnButtonClick; 25 | _button.Pressed += OnButtonPressed; 26 | _button.Released += OnButtonReleased; 27 | 28 | Content = _button; 29 | } 30 | 31 | private void OnButtonClick(object sender, EventArgs e) => OnClicked(); 32 | 33 | private void OnButtonPressed(object sender, EventArgs e) => OnPressed(); 34 | 35 | private void OnButtonReleased(object sender, EventArgs e) => OnReleased(); 36 | 37 | protected override void OnParentSet() 38 | { 39 | base.OnParentSet(); 40 | 41 | if (Parent != null || _button == null) return; 42 | 43 | _button.Clicked -= OnButtonClick; 44 | _button.Pressed -= OnButtonPressed; 45 | _button.Released -= OnButtonReleased; 46 | } 47 | 48 | protected override void OnPropertyChanged(string propertyName = null) 49 | { 50 | base.OnPropertyChanged(propertyName); 51 | 52 | if (propertyName == null) return; 53 | 54 | if (propertyName == TextProperty.PropertyName) _button.Text = Text; 55 | else if (propertyName == TextColorProperty.PropertyName) _button.TextColor = TextColor; 56 | else if (propertyName == FontSizeProperty.PropertyName) _button.FontSize = FontSize; 57 | else if (propertyName == FontFamilyProperty.PropertyName) _button.FontFamily = FontFamily; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/Chips/MaterialLabelChip.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Controls.Chips 4 | { 5 | public class MaterialLabelChip : BaseMaterialChip 6 | { 7 | private readonly Label _label; 8 | 9 | public MaterialLabelChip() 10 | { 11 | _label = new Label 12 | { 13 | Text = Text, 14 | TextColor = TextColor, 15 | FontSize = FontSize, 16 | FontFamily = FontFamily, 17 | VerticalTextAlignment = TextAlignment.Center, 18 | HorizontalTextAlignment = TextAlignment.Center 19 | }; 20 | 21 | Content = _label; 22 | } 23 | 24 | protected override void OnPropertyChanged(string propertyName = null) 25 | { 26 | base.OnPropertyChanged(propertyName); 27 | 28 | if (propertyName == null) return; 29 | 30 | if (propertyName == TextProperty.PropertyName) _label.Text = Text; 31 | else if (propertyName == TextColorProperty.PropertyName) _label.TextColor = TextColor; 32 | else if (propertyName == FontSizeProperty.PropertyName) _label.FontSize = FontSize; 33 | else if (propertyName == FontFamilyProperty.PropertyName) _label.FontFamily = FontFamily; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/GradientBrush.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Collections.Specialized; 5 | using System.ComponentModel; 6 | using Xamarin.Forms; 7 | using XamarinBackgroundKit.Abstractions; 8 | 9 | namespace XamarinBackgroundKit.Controls 10 | { 11 | [ContentProperty(nameof(Gradients))] 12 | public abstract class GradientBrush : BindableObject 13 | { 14 | public static readonly BindableProperty GradientsProperty = BindableProperty.Create( 15 | nameof(Gradients), typeof(IList), typeof(IGradientElement), 16 | propertyChanged: (b, o, n) => ((GradientBrush)b)?.OnGradientsPropertyChanged((IList)o, (IList)n), 17 | defaultValueCreator: b => new ObservableCollection()); 18 | 19 | /// 20 | /// Gets or sets the Gradients of the Background 21 | /// 22 | public IList Gradients 23 | { 24 | get => (IList)GetValue(GradientsProperty); 25 | set => SetValue(GradientsProperty, value); 26 | } 27 | 28 | public static readonly BindableProperty AngleProperty = BindableProperty.Create( 29 | nameof(Angle), typeof(float), typeof(IGradientElement), 0f, 30 | propertyChanged: (b, o, n) => ((GradientBrush)b)?.InvalidateRequested()); 31 | 32 | /// 33 | /// Gets or sets the Angle of the Gradient of the Background 34 | /// 35 | public float Angle 36 | { 37 | get => (float)GetValue(AngleProperty); 38 | set => SetValue(AngleProperty, value); 39 | } 40 | 41 | public event EventHandler InvalidateGradientRequested; 42 | 43 | protected GradientBrush() 44 | { 45 | OnGradientsPropertyChanged(null, Gradients); 46 | } 47 | 48 | private void OnGradientsPropertyChanged(IList oldValue, IList newValue) 49 | { 50 | if (oldValue != null) 51 | { 52 | if (oldValue is INotifyCollectionChanged oldCollection) 53 | { 54 | oldCollection.CollectionChanged -= GradientsCollectionChanged; 55 | } 56 | 57 | foreach (var oldStop in oldValue) 58 | { 59 | oldStop.PropertyChanged -= GradientStopPropertyChanged; 60 | } 61 | } 62 | 63 | if (newValue == null) return; 64 | 65 | if (newValue is INotifyCollectionChanged newCollection) 66 | { 67 | newCollection.CollectionChanged += GradientsCollectionChanged; 68 | } 69 | 70 | foreach (var newStop in newValue) 71 | { 72 | newStop.PropertyChanged += GradientStopPropertyChanged; 73 | } 74 | 75 | InvalidateRequested(); 76 | } 77 | 78 | private void GradientsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 79 | { 80 | if (e.OldItems != null) 81 | { 82 | foreach (var oldItem in e.OldItems) 83 | { 84 | if (!(oldItem is GradientStop oldStop)) continue; 85 | 86 | oldStop.PropertyChanged -= GradientStopPropertyChanged; 87 | } 88 | } 89 | 90 | if (e.NewItems != null) 91 | { 92 | foreach (var newItem in e.NewItems) 93 | { 94 | if (!(newItem is GradientStop newStop)) continue; 95 | 96 | newStop.PropertyChanged += GradientStopPropertyChanged; 97 | } 98 | } 99 | 100 | InvalidateRequested(); 101 | } 102 | 103 | private void GradientStopPropertyChanged(object sender, PropertyChangedEventArgs e) 104 | { 105 | InvalidateRequested(); 106 | } 107 | 108 | public virtual void InvalidateRequested() 109 | { 110 | InvalidateGradientRequested?.Invoke(this, EventArgs.Empty); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/GradientStop.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Controls 4 | { 5 | /// 6 | /// 7 | /// Creates a GradientStop for the Gradient 8 | /// 9 | public class GradientStop : BindableObject 10 | { 11 | public static readonly BindableProperty ColorProperty = BindableProperty.Create( 12 | nameof(Color), typeof(Color), typeof(GradientStop), Color.White); 13 | 14 | /// 15 | /// Gets or sets the Color of the GradientStop 16 | /// 17 | public Color Color 18 | { 19 | get => (Color)GetValue(ColorProperty); 20 | set => SetValue(ColorProperty, value); 21 | } 22 | 23 | public static readonly BindableProperty OffsetProperty = BindableProperty.Create( 24 | nameof(Offset), typeof(float), typeof(GradientStop), 0f); 25 | 26 | /// 27 | /// Gets or sets the Offset of the GradientStop. Must in [0,1] 28 | /// 29 | public float Offset 30 | { 31 | get => (float)GetValue(OffsetProperty); 32 | set => SetValue(OffsetProperty, value); 33 | } 34 | 35 | /// 36 | /// Creates a new GradientStop 37 | /// 38 | public GradientStop() { } 39 | 40 | /// 41 | /// Creates a new GradientStop 42 | /// 43 | /// The Color of the GradientStop 44 | /// The Offset of the GradientStop. Must in [0,1] 45 | public GradientStop(Color color, float offset) 46 | { 47 | Color = color; 48 | Offset = offset; 49 | } 50 | 51 | /// 52 | /// Whether or not two GradientStops are equal 53 | /// 54 | /// The second GradientStop 55 | /// 56 | public override bool Equals(object obj) 57 | { 58 | if (!(obj is GradientStop dest)) return false; 59 | 60 | return Color == dest.Color && System.Math.Abs(Offset - dest.Offset) < 0.00001; 61 | } 62 | 63 | public override int GetHashCode() 64 | { 65 | return -1200350280 + Color.GetHashCode(); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/GradientType.cs: -------------------------------------------------------------------------------- 1 | namespace XamarinBackgroundKit.Controls 2 | { 3 | /// 4 | /// The Type of the Gradient 5 | /// 6 | public enum GradientType 7 | { 8 | Linear, 9 | Radial 10 | } 11 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/LinearGradientBrush.cs: -------------------------------------------------------------------------------- 1 | namespace XamarinBackgroundKit.Controls 2 | { 3 | public class LinearGradientBrush : GradientBrush { } 4 | } 5 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/MaterialCard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace XamarinBackgroundKit.Controls 4 | { 5 | /// 6 | /// 7 | /// MaterialCardView on Android, Card on iOS 8 | /// 9 | [Obsolete("Please use MaterialContentView")] 10 | public class MaterialCard : MaterialContentView { } 11 | } 12 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Controls/MaterialShapeView.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Xamarin.Forms; 3 | using XamarinBackgroundKit.Shapes; 4 | 5 | namespace XamarinBackgroundKit.Controls 6 | { 7 | [DesignTimeVisible(true)] 8 | public class MaterialShapeView : MaterialContentView 9 | { 10 | public static readonly BindableProperty ShapeProperty = BindableProperty.Create( 11 | nameof(Shape), typeof(IBackgroundShape), typeof(MaterialShapeView), new Rect(), 12 | defaultValueCreator: b => new Rect(), 13 | propertyChanged: (b, o, n) => 14 | { 15 | if (!(b is MaterialShapeView shapeView)) return; 16 | 17 | if (o is BaseShape oldShape) 18 | { 19 | oldShape.SetParent(null); 20 | oldShape.RemoveBinding(BindingContextProperty); 21 | } 22 | 23 | if (n is BaseShape newShape) 24 | { 25 | newShape.SetParent(shapeView); 26 | newShape.SetBinding(BindingContextProperty, new Binding("BindingContext", source: shapeView)); 27 | } 28 | }); 29 | 30 | public IBackgroundShape Shape 31 | { 32 | get => (IBackgroundShape)GetValue(ShapeProperty); 33 | set => SetValue(ShapeProperty, value); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Effects/BackgroundEffect.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Controls; 3 | using XamarinBackgroundKit.Extensions; 4 | 5 | namespace XamarinBackgroundKit.Effects 6 | { 7 | public class BackgroundEffect : RoutingEffect 8 | { 9 | #region Attached Properties 10 | 11 | public static readonly BindableProperty BackgroundProperty = BindableProperty.CreateAttached( 12 | "Background", typeof(Background), typeof(BackgroundEffect), new Background(), 13 | propertyChanged: (b, o, n) => b.AddOrRemoveEffect(() => true)); 14 | 15 | public static Background GetBackground(BindableObject view) => (Background)view.GetValue(BackgroundProperty); 16 | 17 | public static void SetBackground(BindableObject view, Background value) => view.SetValue(BackgroundProperty, value); 18 | 19 | #endregion 20 | 21 | public BackgroundEffect() : base("XamarinBackgroundKit.BackgroundEffect") { } 22 | } 23 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Effects/TextEffect.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Extensions; 3 | 4 | namespace XamarinBackgroundKit.Effects 5 | { 6 | public static class Text 7 | { 8 | #region Bindable Properties 9 | 10 | public static readonly BindableProperty NoButtonCapsProperty = BindableProperty.CreateAttached( 11 | "NoButtonCaps", typeof(bool), typeof(Text), false, propertyChanged: (b, o, n) => 12 | b.AddOrRemoveEffect(() => n is bool noCaps && noCaps)); 13 | 14 | #endregion 15 | 16 | #region Getters and Setters 17 | 18 | public static bool GetNoButtonCaps(BindableObject view) => (bool)view.GetValue(NoButtonCapsProperty); 19 | 20 | public static void SetNoButtonCaps(BindableObject view, bool value) => view.SetValue(NoButtonCapsProperty, value); 21 | 22 | #endregion 23 | } 24 | 25 | public class NoButtonTextCapsEffect : RoutingEffect 26 | { 27 | public NoButtonTextCapsEffect() : base("XamarinBackgroundKit.NoButtonTextCapsEffect") { } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Extensions/AngleExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Xamarin.Forms; 5 | 6 | namespace XamarinBackgroundKit.Extensions 7 | { 8 | public static class AngleExtensions 9 | { 10 | public static float[] ToStartEndPoint(this float angle) => ((double)angle).ToStartEndPoint(); 11 | 12 | public static float[] ToStartEndPoint(this double angle) 13 | { 14 | var points = angle.ToPoints().ToArray(); 15 | 16 | if (points.Length != 2) return null; 17 | 18 | return new[] 19 | { 20 | (float)points[0].X, 21 | (float)points[0].Y, 22 | (float)points[1].X, 23 | (float)points[1].Y 24 | }; 25 | } 26 | 27 | public static IEnumerable ToPoints(this float angle) => ((double)angle).ToPoints(); 28 | 29 | public static IEnumerable ToPoints(this double angle) 30 | { 31 | var d = Math.Pow(2, .5); 32 | var eps = Math.Pow(2, -52); 33 | 34 | var finalAngle = angle % 360; 35 | 36 | var startPointRadians = (180 - finalAngle).ToRadians(); 37 | var startX = d * Math.Cos(startPointRadians); 38 | var startY = d * Math.Sin(startPointRadians); 39 | 40 | var endPointRadians = (360 - finalAngle).ToRadians(); 41 | var endX = d * Math.Cos(endPointRadians); 42 | var endY = d * Math.Sin(endPointRadians); 43 | 44 | return new[] 45 | { 46 | new Point(startX.CheckForOverflow(eps), startY.CheckForOverflow(eps)), 47 | new Point(endX.CheckForOverflow(eps), endY.CheckForOverflow(eps)) 48 | }; 49 | } 50 | 51 | public static double ToRadians(this int angle) 52 | { 53 | return Math.PI * angle / 180; 54 | } 55 | 56 | public static double ToRadians(this float angle) 57 | { 58 | return Math.PI * angle / 180; 59 | } 60 | 61 | public static double ToRadians(this double angle) 62 | { 63 | return Math.PI * angle / 180; 64 | } 65 | 66 | private static double CheckForOverflow(this double value, double eps) 67 | { 68 | return value <= 0 || Math.Abs(value) <= eps ? 0f : value; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Extensions/BackgroundExtensions.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Controls; 3 | using XamarinBackgroundKit.Effects; 4 | 5 | namespace XamarinBackgroundKit.Extensions 6 | { 7 | public static class BackgroundExtensions 8 | { 9 | public static T ApplyBackground(this T element, Background background) where T : Element 10 | { 11 | BackgroundEffect.SetBackground(element, background); 12 | return element; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Extensions/CommandExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | 3 | namespace XamarinBackgroundKit.Extensions 4 | { 5 | public static class CommandExtensions 6 | { 7 | public static void CheckAndExecute(this ICommand command, object param) 8 | { 9 | if (command == null || !command.CanExecute(param)) return; 10 | command.Execute(param); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Extensions/CornerRadiusExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xamarin.Forms; 3 | using XamarinBackgroundKit.Abstractions; 4 | 5 | namespace XamarinBackgroundKit.Extensions 6 | { 7 | public static class CornerRadiusExtensions 8 | { 9 | private static readonly CornerRadius DefaultCornerRadius = new CornerRadius(0d); 10 | 11 | public static bool IsEmpty(this ICornerElement cornerRadius) 12 | { 13 | return cornerRadius.CornerRadius.IsEmpty(); 14 | } 15 | 16 | public static bool IsEmpty(this CornerRadius cornerRadius) 17 | { 18 | return cornerRadius == DefaultCornerRadius; 19 | } 20 | 21 | public static bool IsAllRadius(this ICornerElement cornerRadius) 22 | { 23 | return cornerRadius.CornerRadius.IsAllRadius(); 24 | } 25 | 26 | public static bool IsAllRadius(this CornerRadius cornerRadius) 27 | { 28 | return Math.Abs(( 29 | (cornerRadius.TopLeft + 30 | cornerRadius.TopRight + 31 | cornerRadius.BottomLeft + 32 | cornerRadius.BottomRight) / 4) - cornerRadius.TopLeft) < 0.001; 33 | } 34 | 35 | public static float[] ToRadii(this ICornerElement cornerElement, double density) 36 | { 37 | return cornerElement.CornerRadius.ToRadii(density); 38 | } 39 | 40 | public static float[] ToRadii(this CornerRadius cornerRadius, double density) 41 | { 42 | return new[] 43 | { 44 | ToPixels(cornerRadius.TopLeft, density), 45 | ToPixels(cornerRadius.TopLeft, density), 46 | ToPixels(cornerRadius.TopRight, density), 47 | ToPixels(cornerRadius.TopRight, density), 48 | ToPixels(cornerRadius.BottomRight, density), 49 | ToPixels(cornerRadius.BottomRight, density), 50 | ToPixels(cornerRadius.BottomLeft, density), 51 | ToPixels(cornerRadius.BottomLeft, density) 52 | }; 53 | } 54 | 55 | public static float ToPixels(double units, double density) 56 | { 57 | return (float)(units * density); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Extensions/ElementExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Xamarin.Forms; 4 | 5 | namespace XamarinBackgroundKit.Extensions 6 | { 7 | public static class ElementExtensions 8 | { 9 | public static void AddOrRemoveEffect(this BindableObject bindable, Func applyEffect) where T : RoutingEffect 10 | { 11 | if (!(bindable is Element view)) return; 12 | 13 | var goingToApply = applyEffect(); 14 | var effect = view.Effects?.FirstOrDefault(e => e is T); 15 | 16 | if (goingToApply && effect == null) 17 | { 18 | view.Effects?.Add((T)Activator.CreateInstance(typeof(T))); 19 | } 20 | else if (effect != null) 21 | { 22 | view.Effects?.Remove(effect); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Extensions/GradientsExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using XamarinBackgroundKit.Controls; 4 | 5 | namespace XamarinBackgroundKit.Extensions 6 | { 7 | public static class GradientsExtensions 8 | { 9 | public static bool AreEqual(this IList source, IList dest) 10 | { 11 | /* No need to update the layer if the gradients are the same */ 12 | if (source == null && dest == null) return true; 13 | if (source == null || dest == null) return false; 14 | if (source.Count != dest.Count) return false; 15 | 16 | /* Find the different gradients */ 17 | var differencesOneWay = source.Where(x => !dest.Any(y => y.Equals(x))).ToList(); 18 | var differencesSecWay = dest.Where(x => !source.Any(y => y.Equals(x))).ToList(); 19 | 20 | /* If no differences found, then return */ 21 | return differencesOneWay.Count == 0 && differencesSecWay.Count == 0; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/MarkupExtensions/BgProviderExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xamarin.Forms.Xaml; 3 | using XamarinBackgroundKit.Controls; 4 | 5 | namespace XamarinBackgroundKit.MarkupExtensions 6 | { 7 | public class BgProviderExtension : Background, IMarkupExtension 8 | { 9 | public Background ProvideValue(IServiceProvider serviceProvider) => this; 10 | 11 | object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) => ProvideValue(serviceProvider); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/MarkupExtensions/LinearGradientExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Xamarin.Forms; 4 | using Xamarin.Forms.Xaml; 5 | using XamarinBackgroundKit.Controls; 6 | 7 | namespace XamarinBackgroundKit.MarkupExtensions 8 | { 9 | [ContentProperty(nameof(Gradients))] 10 | public class LinearGradientExtension : IMarkupExtension 11 | { 12 | public Color Start { get; set; } = Color.Default; 13 | public Color End { get; set; } = Color.Default; 14 | public float Angle { get; set; } 15 | public string Gradients { get; set; } 16 | 17 | public LinearGradientBrush ProvideValue(IServiceProvider serviceProvider) 18 | { 19 | if (Start != Color.Default && End != Color.Default) return FromStartEnd(); 20 | return !string.IsNullOrWhiteSpace(Gradients) ? FromString() : null; 21 | } 22 | 23 | private LinearGradientBrush FromStartEnd() 24 | { 25 | return new LinearGradientBrush 26 | { 27 | Angle = Angle, 28 | Gradients = 29 | { 30 | new GradientStop(Start, 0), 31 | new GradientStop(End, 1) 32 | } 33 | }; 34 | } 35 | 36 | private LinearGradientBrush FromString() 37 | { 38 | var gradients = new List(); 39 | var gradientStrings = Gradients.Split(','); 40 | if (gradientStrings.Length < 2) return null; 41 | 42 | var offset = 0f; 43 | var offsetDelta = 1f / (gradientStrings.Length - 1); 44 | foreach (var gradientString in gradientStrings) 45 | { 46 | var trimmedGradientString = gradientString.Trim(); 47 | 48 | Color? color = null; 49 | try 50 | { 51 | if (trimmedGradientString.Contains("#")) 52 | { 53 | color = Color.FromHex(trimmedGradientString); 54 | } 55 | else 56 | { 57 | var systemColor = System.Drawing.Color.FromName(trimmedGradientString); 58 | color = new Color(systemColor.R, systemColor.G, systemColor.B, systemColor.A); 59 | } 60 | } 61 | catch (Exception) 62 | { 63 | // ignored 64 | } 65 | 66 | if (color == null) return null; 67 | gradients.Add(new GradientStop(color.Value, offset)); 68 | 69 | offset += offsetDelta; 70 | } 71 | 72 | return new LinearGradientBrush 73 | { 74 | Angle = Angle, 75 | Gradients = gradients 76 | }; 77 | 78 | } 79 | 80 | object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) => ProvideValue(serviceProvider); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using Xamarin.Forms.Internals; 3 | 4 | [assembly: Preserve(AllMembers = true)] 5 | 6 | [assembly: XmlnsDefinition("http://xamarin.com/schemas/2014/forms/background", "XamarinBackgroundKit.Shapes")] 7 | [assembly: XmlnsDefinition("http://xamarin.com/schemas/2014/forms/background", "XamarinBackgroundKit.Effects")] 8 | [assembly: XmlnsDefinition("http://xamarin.com/schemas/2014/forms/background", "XamarinBackgroundKit.Controls")] 9 | [assembly: XmlnsDefinition("http://xamarin.com/schemas/2014/forms/background", "XamarinBackgroundKit.MarkupExtensions")] -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/Arc.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Shapes 4 | { 5 | public class Arc : BaseShape 6 | { 7 | public static readonly BindableProperty PositionProperty = BindableProperty.Create( 8 | nameof(Position), typeof(ShapePosition), typeof(Arc), ShapePosition.Top, 9 | propertyChanged: (b, o, n) => ((Arc)b)?.InvalidateShape()); 10 | 11 | public ShapePosition Position 12 | { 13 | get => (ShapePosition)GetValue(PositionProperty); 14 | set => SetValue(PositionProperty, value); 15 | } 16 | 17 | public static readonly BindableProperty IsCropInsideProperty = BindableProperty.Create( 18 | nameof(IsCropInside), typeof(bool), typeof(Arc), false, 19 | propertyChanged: (b, o, n) => ((Arc)b)?.InvalidateShape()); 20 | 21 | public bool IsCropInside 22 | { 23 | get => (bool)GetValue(IsCropInsideProperty); 24 | set => SetValue(IsCropInsideProperty, value); 25 | } 26 | 27 | public static readonly BindableProperty ArcHeightProperty = BindableProperty.Create( 28 | nameof(ArcHeight), typeof(double), typeof(Arc), 0d, 29 | propertyChanged: (b, o, n) => ((Arc)b)?.InvalidateShape()); 30 | 31 | public double ArcHeight 32 | { 33 | get => (double)GetValue(ArcHeightProperty); 34 | set => SetValue(ArcHeightProperty, value); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/BaseShape.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xamarin.Forms; 3 | using XamarinBackgroundKit.Abstractions; 4 | using XamarinBackgroundKit.Controls; 5 | 6 | namespace XamarinBackgroundKit.Shapes 7 | { 8 | public class BaseShape : BindableObject, IBackgroundShape 9 | { 10 | private WeakReference _parentWeakRef; 11 | private IMaterialVisualElement Background 12 | { 13 | get 14 | { 15 | if (_parentWeakRef == null) return null; 16 | if (!_parentWeakRef.TryGetTarget(out var parent)) return null; 17 | 18 | return parent is IBackgroundElement backgroundElement 19 | ? backgroundElement.Background 20 | : null; 21 | } 22 | } 23 | 24 | public double BorderWidth => Background?.BorderWidth ?? 0d; 25 | public bool NeedsBorderInset => BorderWidth > 0 && Background.BorderStyle == BorderStyle.Outer; 26 | 27 | public event EventHandler ShapeInvalidateRequested; 28 | 29 | public virtual void InvalidateShape() 30 | { 31 | ShapeInvalidateRequested?.Invoke(this, EventArgs.Empty); 32 | } 33 | 34 | public void SetParent(VisualElement parent) 35 | { 36 | _parentWeakRef = new WeakReference(parent); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/Circle.cs: -------------------------------------------------------------------------------- 1 | namespace XamarinBackgroundKit.Shapes 2 | { 3 | public class Circle : BaseShape { } 4 | } 5 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/CornerClip.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Shapes 4 | { 5 | public class CornerClip : BaseShape 6 | { 7 | public static readonly BindableProperty ClipSizeProperty = BindableProperty.Create( 8 | nameof(ClipSize), typeof(CornerRadius), typeof(CornerClip), new CornerRadius(0d), 9 | propertyChanged: (b, o, n) => ((CornerClip)b)?.InvalidateShape(), 10 | defaultValueCreator: b => new CornerRadius(0d)); 11 | 12 | public CornerRadius ClipSize 13 | { 14 | get => (CornerRadius)GetValue(ClipSizeProperty); 15 | set => SetValue(ClipSizeProperty, value); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/Diagonal.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Shapes 4 | { 5 | public class Diagonal : BaseShape 6 | { 7 | public static readonly BindableProperty PositionProperty = BindableProperty.Create( 8 | nameof(Position), typeof(ShapePosition), typeof(Diagonal), ShapePosition.Top, 9 | propertyChanged: (b, o, n) => ((Diagonal)b)?.InvalidateShape()); 10 | 11 | public ShapePosition Position 12 | { 13 | get => (ShapePosition)GetValue(PositionProperty); 14 | set => SetValue(PositionProperty, value); 15 | } 16 | 17 | public static readonly BindableProperty DirectionProperty = BindableProperty.Create( 18 | nameof(Direction), typeof(ShapeDirection), typeof(Diagonal), ShapeDirection.Left, 19 | propertyChanged: (b, o, n) => ((Diagonal)b)?.InvalidateShape()); 20 | 21 | public ShapeDirection Direction 22 | { 23 | get => (ShapeDirection)GetValue(DirectionProperty); 24 | set => SetValue(DirectionProperty, value); 25 | } 26 | 27 | public static readonly BindableProperty AngleProperty = BindableProperty.Create( 28 | nameof(Angle), typeof(double), typeof(Diagonal), 0d, 29 | propertyChanged: (b, o, n) => ((Diagonal)b)?.InvalidateShape()); 30 | 31 | public double Angle 32 | { 33 | get => (double)GetValue(AngleProperty); 34 | set => SetValue(AngleProperty, value); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/Rect.cs: -------------------------------------------------------------------------------- 1 | namespace XamarinBackgroundKit.Shapes 2 | { 3 | public class Rect : BaseShape { } 4 | } 5 | 6 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/RoundRect.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using XamarinBackgroundKit.Abstractions; 3 | using XamarinBackgroundKit.Controls.Base; 4 | 5 | namespace XamarinBackgroundKit.Shapes 6 | { 7 | public class RoundRect : BaseShape, ICornerElement 8 | { 9 | public static readonly BindableProperty CornerRadiusProperty = CornerElement.CornerRadiusProperty; 10 | 11 | public CornerRadius CornerRadius 12 | { 13 | get => (CornerRadius)GetValue(CornerRadiusProperty); 14 | set => SetValue(CornerRadiusProperty, value); 15 | } 16 | 17 | public void OnCornerRadiusPropertyChanged(CornerRadius oldValue, CornerRadius newValue) => InvalidateShape(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/ShapeDirection.cs: -------------------------------------------------------------------------------- 1 | namespace XamarinBackgroundKit.Shapes 2 | { 3 | public enum ShapeDirection 4 | { 5 | Left, 6 | Right 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/ShapePosition.cs: -------------------------------------------------------------------------------- 1 | namespace XamarinBackgroundKit.Shapes 2 | { 3 | public enum ShapePosition 4 | { 5 | Left, 6 | Top, 7 | Right, 8 | Bottom 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/Shapes/Triangle.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKit.Shapes 4 | { 5 | public class Triangle : BaseShape 6 | { 7 | public static readonly BindableProperty PointAProperty = BindableProperty.Create( 8 | nameof(PointA), typeof(Point), typeof(Triangle), new Point(), 9 | propertyChanged: (b, o, n) => ((Triangle)b)?.InvalidateShape()); 10 | 11 | public Point PointA 12 | { 13 | get => (Point)GetValue(PointAProperty); 14 | set => SetValue(PointAProperty, value); 15 | } 16 | 17 | public static readonly BindableProperty PointBProperty = BindableProperty.Create( 18 | nameof(PointB), typeof(Point), typeof(Triangle), new Point(), 19 | propertyChanged: (b, o, n) => ((Triangle)b)?.InvalidateShape()); 20 | 21 | public Point PointB 22 | { 23 | get => (Point)GetValue(PointBProperty); 24 | set => SetValue(PointBProperty, value); 25 | } 26 | 27 | public static readonly BindableProperty PointCProperty = BindableProperty.Create( 28 | nameof(PointC), typeof(Point), typeof(Triangle), new Point(), 29 | propertyChanged: (b, o, n) => ((Triangle)b)?.InvalidateShape()); 30 | 31 | public Point PointC 32 | { 33 | get => (Point)GetValue(PointCProperty); 34 | set => SetValue(PointCProperty, value); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKit/XamarinBackgroundKit.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories) and given a Build Action of "AndroidAsset". 3 | 4 | These files will be deployed with you package and will be accessible using Android's 5 | AssetManager, like this: 6 | 7 | public class ReadAsset : Activity 8 | { 9 | protected override void OnCreate (Bundle bundle) 10 | { 11 | base.OnCreate (bundle); 12 | 13 | InputStream input = Assets.Open ("my_asset.txt"); 14 | } 15 | } 16 | 17 | Additionally, some Android functions will automatically load asset files: 18 | 19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); 20 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content.PM; 3 | using Android.Runtime; 4 | using Android.OS; 5 | using Rg.Plugins.Popup; 6 | using Xamarin.Forms; 7 | using Xamarin.Forms.Platform.Android; 8 | using XamarinBackgroundKit.Android; 9 | using XEPlatform = Xamarin.Essentials.Platform; 10 | 11 | namespace XamarinBackgroundKitSample.Droid 12 | { 13 | [Activity( 14 | Label = "XamarinBackgroundKitSample", 15 | Icon = "@mipmap/icon", 16 | Theme = "@style/MainTheme.Launcher", 17 | MainLauncher = true, 18 | ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] 19 | public class MainActivity : FormsAppCompatActivity 20 | { 21 | protected override void OnCreate(Bundle savedInstanceState) 22 | { 23 | TabLayoutResource = Resource.Layout.Tabbar; 24 | ToolbarResource = Resource.Layout.Toolbar; 25 | 26 | base.OnCreate(savedInstanceState); 27 | 28 | BackgroundKit.Init(); 29 | 30 | Popup.Init(this); 31 | Forms.Init(this, savedInstanceState); 32 | XEPlatform.Init(this, savedInstanceState); 33 | FormsMaterial.Init(this, savedInstanceState); 34 | 35 | LoadApplication(new App()); 36 | } 37 | 38 | public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) 39 | { 40 | XEPlatform.OnRequestPermissionsResult(requestCode, permissions, grantResults); 41 | 42 | base.OnRequestPermissionsResult(requestCode, permissions, grantResults); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using Android.App; 4 | 5 | [assembly: AssemblyTitle("XamarinBackgroundKitSample.Android")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("XamarinBackgroundKitSample.Android")] 10 | [assembly: AssemblyCopyright("Copyright © 2014")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | [assembly: ComVisible(false)] 14 | 15 | [assembly: AssemblyVersion("1.0.0.0")] 16 | [assembly: AssemblyFileVersion("1.0.0.0")] 17 | 18 | [assembly: UsesPermission(Android.Manifest.Permission.Internet)] 19 | [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] 20 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.xml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable-hdpi/ 12 | icon.png 13 | 14 | drawable-ldpi/ 15 | icon.png 16 | 17 | drawable-mdpi/ 18 | icon.png 19 | 20 | layout/ 21 | main.xml 22 | 23 | values/ 24 | strings.xml 25 | 26 | In order to get the build system to recognize Android resources, set the build action to 27 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 28 | instead operate on resource IDs. When you compile an Android application that uses resources, 29 | the build system will package the resources for distribution and generate a class called 30 | "Resource" that contains the tokens for each one of the resources included. For example, 31 | for the above Resources layout, this is what the Resource class would expose: 32 | 33 | public class Resource { 34 | public class drawable { 35 | public const int icon = 0x123; 36 | } 37 | 38 | public class layout { 39 | public const int main = 0x456; 40 | } 41 | 42 | public class strings { 43 | public const int first_string = 0xabc; 44 | public const int second_string = 0xbcd; 45 | } 46 | } 47 | 48 | You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main 49 | to reference the layout/main.xml file, or Resource.strings.first_string to reference the first 50 | string in the dictionary file values/strings.xml. 51 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-hdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-hdpi/ic_done.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-hdpi/ic_done_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-hdpi/ic_done_grey.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-hdpi/xamagon_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-hdpi/xamagon_preview.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-mdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-mdpi/ic_done.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-mdpi/ic_done_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-mdpi/ic_done_grey.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-xhdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-xhdpi/ic_done.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-xhdpi/ic_done_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-xhdpi/ic_done_grey.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-xhdpi/xamagon_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-xhdpi/xamagon_preview.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-xxhdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-xxhdpi/ic_done.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-xxhdpi/ic_done_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-xxhdpi/ic_done_grey.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-xxhdpi/xamagon_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-xxhdpi/xamagon_preview.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-xxxhdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-xxxhdpi/ic_done.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-xxxhdpi/ic_done_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-xxxhdpi/ic_done_grey.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable-xxxhdpi/xamagon_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/drawable-xxxhdpi/xamagon_preview.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/drawable/launch_screen.axml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/layout/Tabbar.axml: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/layout/Toolbar.axml: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-anydpi-v26/icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-anydpi-v26/icon_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-hdpi/icon.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-hdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-hdpi/launcher_foreground.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-mdpi/icon.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-mdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-mdpi/launcher_foreground.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-xhdpi/icon.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-xhdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-xhdpi/launcher_foreground.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-xxhdpi/icon.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-xxhdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-xxhdpi/launcher_foreground.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-xxxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-xxxhdpi/icon.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ececec 4 | #3F51B5 5 | #303F9F 6 | #FF4081 7 | 8 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.Android/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 26 | 27 | 30 | 31 | 32 | 35 | 36 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using Foundation; 2 | using Rg.Plugins.Popup; 3 | using UIKit; 4 | using Xamarin.Forms; 5 | using Xamarin.Forms.Platform.iOS; 6 | using XamarinBackgroundKit.iOS; 7 | 8 | namespace XamarinBackgroundKitSample.iOS 9 | { 10 | [Register("AppDelegate")] 11 | public class AppDelegate : FormsApplicationDelegate 12 | { 13 | public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions) 14 | { 15 | Popup.Init(); 16 | Forms.Init(); 17 | FormsMaterial.Init(); 18 | BackgroundKit.Init(); 19 | 20 | LoadApplication(new App()); 21 | 22 | return base.FinishedLaunching(uiApplication, launchOptions); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "scale": "2x", 5 | "size": "20x20", 6 | "idiom": "iphone", 7 | "filename": "Icon40.png" 8 | }, 9 | { 10 | "scale": "3x", 11 | "size": "20x20", 12 | "idiom": "iphone", 13 | "filename": "Icon60.png" 14 | }, 15 | { 16 | "scale": "2x", 17 | "size": "29x29", 18 | "idiom": "iphone", 19 | "filename": "Icon58.png" 20 | }, 21 | { 22 | "scale": "3x", 23 | "size": "29x29", 24 | "idiom": "iphone", 25 | "filename": "Icon87.png" 26 | }, 27 | { 28 | "scale": "2x", 29 | "size": "40x40", 30 | "idiom": "iphone", 31 | "filename": "Icon80.png" 32 | }, 33 | { 34 | "scale": "3x", 35 | "size": "40x40", 36 | "idiom": "iphone", 37 | "filename": "Icon120.png" 38 | }, 39 | { 40 | "scale": "2x", 41 | "size": "60x60", 42 | "idiom": "iphone", 43 | "filename": "Icon120.png" 44 | }, 45 | { 46 | "scale": "3x", 47 | "size": "60x60", 48 | "idiom": "iphone", 49 | "filename": "Icon180.png" 50 | }, 51 | { 52 | "scale": "1x", 53 | "size": "20x20", 54 | "idiom": "ipad", 55 | "filename": "Icon20.png" 56 | }, 57 | { 58 | "scale": "2x", 59 | "size": "20x20", 60 | "idiom": "ipad", 61 | "filename": "Icon40.png" 62 | }, 63 | { 64 | "scale": "1x", 65 | "size": "29x29", 66 | "idiom": "ipad", 67 | "filename": "Icon29.png" 68 | }, 69 | { 70 | "scale": "2x", 71 | "size": "29x29", 72 | "idiom": "ipad", 73 | "filename": "Icon58.png" 74 | }, 75 | { 76 | "scale": "1x", 77 | "size": "40x40", 78 | "idiom": "ipad", 79 | "filename": "Icon40.png" 80 | }, 81 | { 82 | "scale": "2x", 83 | "size": "40x40", 84 | "idiom": "ipad", 85 | "filename": "Icon80.png" 86 | }, 87 | { 88 | "scale": "1x", 89 | "size": "76x76", 90 | "idiom": "ipad", 91 | "filename": "Icon76.png" 92 | }, 93 | { 94 | "scale": "2x", 95 | "size": "76x76", 96 | "idiom": "ipad", 97 | "filename": "Icon152.png" 98 | }, 99 | { 100 | "scale": "2x", 101 | "size": "83.5x83.5", 102 | "idiom": "ipad", 103 | "filename": "Icon167.png" 104 | }, 105 | { 106 | "scale": "1x", 107 | "size": "1024x1024", 108 | "idiom": "ios-marketing", 109 | "filename": "Icon1024.png" 110 | } 111 | ], 112 | "properties": {}, 113 | "info": { 114 | "version": 1, 115 | "author": "xcode" 116 | } 117 | } -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIDeviceFamily 6 | 7 | 1 8 | 2 9 | 10 | UISupportedInterfaceOrientations 11 | 12 | UIInterfaceOrientationPortrait 13 | UIInterfaceOrientationLandscapeLeft 14 | UIInterfaceOrientationLandscapeRight 15 | 16 | UISupportedInterfaceOrientations~ipad 17 | 18 | UIInterfaceOrientationPortrait 19 | UIInterfaceOrientationPortraitUpsideDown 20 | UIInterfaceOrientationLandscapeLeft 21 | UIInterfaceOrientationLandscapeRight 22 | 23 | MinimumOSVersion 24 | 9.0 25 | CFBundleDisplayName 26 | XamarinBackgroundKitSample 27 | CFBundleIdentifier 28 | com.companyname.XamarinBackgroundKitSample 29 | CFBundleVersion 30 | 1.0 31 | UILaunchStoryboardName 32 | LaunchScreen 33 | CFBundleName 34 | XamarinBackgroundKitSample 35 | XSAppIconAssets 36 | Assets.xcassets/AppIcon.appiconset 37 | UIMainStoryboardFile 38 | LaunchScreen 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Main.cs: -------------------------------------------------------------------------------- 1 | using UIKit; 2 | 3 | namespace XamarinBackgroundKitSample.iOS 4 | { 5 | public class Application 6 | { 7 | private static void Main(string[] args) 8 | { 9 | UIApplication.Main(args, null, "AppDelegate"); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("XamarinBackgroundKitSample.iOS")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyConfiguration("")] 7 | [assembly: AssemblyCompany("")] 8 | [assembly: AssemblyProduct("XamarinBackgroundKitSample.iOS")] 9 | [assembly: AssemblyCopyright("Copyright © 2014")] 10 | [assembly: AssemblyTrademark("")] 11 | [assembly: AssemblyCulture("")] 12 | 13 | [assembly: ComVisible(false)] 14 | 15 | [assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")] 16 | 17 | [assembly: AssemblyVersion("1.0.0.0")] 18 | [assembly: AssemblyFileVersion("1.0.0.0")] 19 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/Icon60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Resources/Icon60.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/Icon60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Resources/Icon60@2x.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/Icon60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Resources/Icon60@3x.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Resources/ic_done.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/ic_done@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Resources/ic_done@2x.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/ic_done@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Resources/ic_done@3x.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/ic_done_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Resources/ic_done_grey.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/ic_done_grey@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Resources/ic_done_grey@2x.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample.iOS/Resources/ic_done_grey@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChasakisD/Xamarin.Forms.BackgroundKit/22924530cdb1a0b4dd346706cc20427a3ef43c6e/src/XamarinBackgroundKitSample.iOS/Resources/ic_done_grey@3x.png -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample/App.xaml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace XamarinBackgroundKitSample 4 | { 5 | public partial class App 6 | { 7 | public App() 8 | { 9 | InitializeComponent(); 10 | 11 | Device.SetFlags(new[] { 12 | "SwipeView_Experimental", 13 | "CarouselView_Experimental", 14 | "IndicatorView_Experimental" 15 | }); 16 | 17 | MainPage = new NavigationPage(new ExploreViewsPage()) 18 | { 19 | BarBackgroundColor = Color.White, 20 | BarTextColor = Color.FromHex("#2D2D2D") 21 | }; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/XamarinBackgroundKitSample/ColorPickerPage.xaml: -------------------------------------------------------------------------------- 1 |  2 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 24 | 25 | 26 | 31 | 32 | 39 | 40 | 41 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |