Skip to content

Instantly share code, notes, and snippets.

@mattleibow
Created August 24, 2020 00:21
Show Gist options
  • Save mattleibow/47c18830fa5cf4ddf665567b56f16015 to your computer and use it in GitHub Desktop.
Save mattleibow/47c18830fa5cf4ddf665567b56f16015 to your computer and use it in GitHub Desktop.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Input;
using SkiaSharp.Extended.Controls;
using Xamarin.Forms;
namespace SkiaSharpDemo.Demos
{
public partial class ConfettiPage : ContentPage
{
public ConfettiPage()
{
InitializeComponent();
BindingContext = this;
}
private void OnTapped(object sender, EventArgs e)
{
confettiView.Systems!.Add(new SKConfettiSystem
{
Emitter = SKConfettiEmitter.Burst(200)
});
}
}
internal class OptionButtonsManager
{
// TODO: this should probably be an event...
private static readonly ICommand OptionTappedCommand = new Command<View>(OnOptionTapped);
private bool isSubscribed;
public void OnChildAdded(object sender, ElementEventArgs e)
{
if (e.Element is Button button)
{
button.Command = OptionTappedCommand;
button.CommandParameter = button;
}
}
public void OnChildRemoved(object sender, ElementEventArgs e)
{
if (e.Element is Button button)
{
button.Command = null;
button.CommandParameter = null;
}
}
public void UpdateChildren(Layout<View> layout)
{
foreach (var child in layout.Children)
{
if (child is Button button)
{
button.Command = OptionTappedCommand;
button.CommandParameter = button;
}
}
}
public void Subscribe(Layout<View> layout)
{
if (isSubscribed)
return;
layout.ChildAdded += OnChildAdded;
layout.ChildRemoved += OnChildRemoved;
isSubscribed = true;
}
private static void OnOptionTapped(View button)
{
const string Selected = "Selected";
const string Unselected = "Unselected";
if (!(button?.Parent is Layout<View> parent) || !(button.BindingContext is object item))
return;
var style = OptionButtons.GetSelectionMode(parent);
if (style == SelectionMode.None)
return;
var selectedItems = OptionButtons.GetSelectedItems(parent);
if (style != SelectionMode.Multiple)
{
selectedItems?.Clear();
foreach (var btn in parent.Children)
{
if (btn != button)
VisualStateManager.GoToState(btn, Unselected);
}
}
var shouldSelect = false;
// update the selected items list
if (selectedItems != null)
{
shouldSelect = !selectedItems.Contains(item);
if (shouldSelect)
selectedItems.Add(item);
else
selectedItems.Remove(item);
}
// updated the selected item
OptionButtons.SetSelectedItem(parent, item);
VisualStateManager.GoToState(button, shouldSelect ? Selected : Unselected);
}
}
public static class OptionButtons
{
// OptionButtonsManager
private static OptionButtonsManager? GetOptionButtonsManager(BindableObject obj) =>
(OptionButtonsManager?)obj.GetValue(OptionButtonsManagerProperty);
private static readonly BindableProperty OptionButtonsManagerProperty = BindableProperty.CreateAttached(
"OptionButtonsManager",
typeof(OptionButtonsManager),
typeof(Layout<View>),
null,
defaultValueCreator: b => new OptionButtonsManager());
// SelectionMode
public static SelectionMode GetSelectionMode(BindableObject obj) =>
(SelectionMode)obj.GetValue(SelectionModeProperty);
public static void SetSelectionMode(BindableObject obj, SelectionMode value) =>
obj.SetValue(SelectionModeProperty, value);
public static readonly BindableProperty SelectionModeProperty = BindableProperty.CreateAttached(
"SelectionMode",
typeof(SelectionMode),
typeof(Layout<View>),
SelectionMode.Single,
propertyChanged: (b, o, n) => UpdateButtons(b));
// SelectedItems
public static IList<object>? GetSelectedItems(BindableObject obj) =>
(IList<object>?)obj.GetValue(SelectedItemsProperty);
public static void SetSelectedItems(BindableObject obj, IList<object>? value) =>
obj.SetValue(SelectedItemsProperty, value);
public static readonly BindableProperty SelectedItemsProperty = BindableProperty.CreateAttached(
"SelectedItems",
typeof(IList<object>),
typeof(Layout<View>),
null,
defaultValueCreator: b => new List<object>());
// SelectedItem
public static object? GetSelectedItem(BindableObject obj) =>
obj.GetValue(SelectedItemProperty);
public static void SetSelectedItem(BindableObject obj, object? value) =>
obj.SetValue(SelectedItemProperty, value);
public static readonly BindableProperty SelectedItemProperty = BindableProperty.CreateAttached(
"SelectedItem",
typeof(object),
typeof(Layout<View>),
null,
defaultBindingMode: BindingMode.TwoWay);
// ItemsSource
public static IEnumerable? GetItemsSource(BindableObject obj) =>
(IEnumerable?)obj.GetValue(ItemsSourceProperty);
public static void SetItemsSource(BindableObject obj, IEnumerable? value) =>
obj.SetValue(ItemsSourceProperty, value);
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.CreateAttached(
"ItemsSource",
typeof(IEnumerable),
typeof(Layout<View>),
null,
propertyChanged: (b, o, n) =>
{
BindableLayout.SetItemsSource(b, (IEnumerable?)n);
UpdateButtons(b);
});
// ItemTemplate
public static DataTemplate? GetItemTemplate(BindableObject obj) =>
(DataTemplate?)obj.GetValue(ItemTemplateProperty);
public static void SetItemTemplate(BindableObject obj, DataTemplate? value) =>
obj.SetValue(ItemTemplateProperty, value);
public static readonly BindableProperty ItemTemplateProperty = BindableProperty.CreateAttached(
"ItemTemplate",
typeof(DataTemplate),
typeof(Layout<View>),
null,
propertyChanged: (b, o, n) =>
{
BindableLayout.SetItemTemplate(b, (DataTemplate?)n);
UpdateButtons(b);
});
//
private static void UpdateButtons(BindableObject b)
{
if (b is Layout<View> layout && GetOptionButtonsManager(b) is OptionButtonsManager manager)
{
manager.Subscribe(layout);
manager.UpdateChildren(layout);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment