Skip to content

Instantly share code, notes, and snippets.

@rogerwcpt
Created August 7, 2019 11:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rogerwcpt/699d119ac3927cad10cda5254de63acc to your computer and use it in GitHub Desktop.
Save rogerwcpt/699d119ac3927cad10cda5254de63acc to your computer and use it in GitHub Desktop.
Xamarin Forms Gradient ContentView with Item Template and Command
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