Created
August 7, 2019 11:28
-
-
Save rogerwcpt/699d119ac3927cad10cda5254de63acc to your computer and use it in GitHub Desktop.
Xamarin Forms Gradient ContentView with Item Template and Command
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class GradientView : ContentView | |
{ | |
private AbsoluteLayout _absoluteLayout; | |
public Color StartColor { get; set; } = (Color)App.Current.Resources["GradientStartColor"]; | |
public Color EndColor { get; set; } = (Color)App.Current.Resources["GradientEndColor"]; | |
public bool Horizontal { get; set; } = true; | |
public bool HasShadow { get; set; } = true; | |
public double CornerRadius { get; set; } = 0f; | |
private SKCanvasView _canvasView; | |
public GradientView() | |
{ | |
_canvasView = new SKCanvasView(); | |
_canvasView.PaintSurface += OnCanvasViewPaintSurface; | |
AbsoluteLayout.SetLayoutFlags(_canvasView, AbsoluteLayoutFlags.All); | |
AbsoluteLayout.SetLayoutBounds(_canvasView, new Rectangle(1, 1, 1, 1)); | |
_absoluteLayout = new AbsoluteLayout(); | |
_absoluteLayout.Children.Add(_canvasView); | |
Content = _absoluteLayout; | |
} | |
public void SetItems() | |
{ | |
var itemView = GetItemView(); | |
if (itemView != null) | |
{ | |
AbsoluteLayout.SetLayoutFlags(itemView, AbsoluteLayoutFlags.All); | |
AbsoluteLayout.SetLayoutBounds(itemView, new Rectangle(1, 1, 1, 1)); | |
_absoluteLayout.Children.Clear(); | |
_absoluteLayout.Children.Add(_canvasView); | |
_absoluteLayout.Children.Add(itemView); | |
} | |
} | |
public static readonly BindableProperty CommandProperty = | |
BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(GradientView), default(ICommand)); | |
public static readonly BindableProperty ItemsSourceProperty = | |
BindableProperty.Create(nameof(ItemsSource), typeof(object), typeof(RepeaterList), default(object), | |
BindingMode.TwoWay, propertyChanged: ItemsSourceChanged); | |
public static readonly BindableProperty ItemTemplateProperty = | |
BindableProperty.Create(nameof(ItemTemplate), typeof(DataTemplate), typeof(RepeaterList), default(DataTemplate)); | |
public ICommand Command | |
{ | |
get => (ICommand)GetValue(CommandProperty); | |
set => SetValue(CommandProperty, value); | |
} | |
public object ItemsSource | |
{ | |
get => (object)GetValue(ItemsSourceProperty); | |
set => SetValue(ItemsSourceProperty, value); | |
} | |
public DataTemplate ItemTemplate | |
{ | |
get => (DataTemplate)GetValue(ItemTemplateProperty); | |
set => SetValue(ItemTemplateProperty, value); | |
} | |
protected View GetItemView() | |
{ | |
if (ItemTemplate == null) | |
{ | |
return null; | |
} | |
var content = ItemTemplate.CreateContent(); | |
var view = content as View; | |
view.BindingContext = ItemsSource; | |
if (view == null) | |
{ | |
return null; | |
} | |
return view; | |
} | |
private static void ItemsSourceChanged(BindableObject bindable, object oldValue, object newValue) | |
{ | |
var itemsLayout = (GradientView)bindable; | |
itemsLayout.SetItems(); | |
} | |
private void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) | |
{ | |
SKImageInfo info = args.Info; | |
SKSurface surface = args.Surface; | |
SKCanvas canvas = surface.Canvas; | |
canvas.Clear(); | |
var colors = new SKColor[] { StartColor.ToSKColor(), EndColor.ToSKColor() }; | |
SKPoint startPoint = new SKPoint(0, 0); | |
SKPoint endPoint = Horizontal ? new SKPoint(info.Width, 0) : new SKPoint(0, info.Height); | |
var shader = SKShader.CreateLinearGradient(startPoint, endPoint, colors, null, SKShaderTileMode.Clamp); | |
SKPaint paint = new SKPaint | |
{ | |
Style = SKPaintStyle.Fill, | |
Shader = shader | |
}; | |
var drawingRect = new SKRect(0, 0, info.Width, info.Height); | |
if (CornerRadius > 0) | |
{ | |
var cornerRadius = CornerRadius; | |
// Not sure if this adjustment is needed with future versions of Xamarin Forms | |
if (Device.RuntimePlatform == Device.Android) | |
{ | |
cornerRadius = CornerRadius * 4; | |
} | |
canvas.DrawRoundRect(drawingRect, (float)cornerRadius, (float)cornerRadius, paint); | |
} | |
else | |
{ | |
canvas.DrawRect(drawingRect, paint); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment