Added AvatarView and Slider controls

This commit is contained in:
Javier Suárez Ruiz 2022-04-15 12:17:03 +02:00
Родитель 236b2b05ed
Коммит aafc4aa8df
13 изменённых файлов: 1077 добавлений и 6 удалений

Просмотреть файл

@ -7,6 +7,9 @@ namespace AlohaKit.Gallery.ViewModels
{
protected override IEnumerable<SectionModel> CreateItems() => new[]
{
new SectionModel(typeof(AvatarView), "Avatar",
"The Avatar control displays the initials of a person, entity, or group on top of a colored circular background."),
new SectionModel(typeof(LoadingView), "BusyIndicator",
"It can be used to indicate busy status during app loading, data processing, etc."),
@ -22,6 +25,9 @@ namespace AlohaKit.Gallery.ViewModels
new SectionModel(typeof(RatingView), "Rating",
"Rating is a control that allows users to rate by selecting number of items from a predefined number of items."),
new SectionModel(typeof(SliderView), "Slider",
"The Slider is a horizontal bar that can be manipulated by the user to select a double value from a continuous range."),
new SectionModel(typeof(ToggleSwitchView), "ToggleSwitch",
"The ToggleSwitch is a horizontal toggle button that can be manipulated by the user to toggle between on and off states."),
};

Просмотреть файл

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="AlohaKit.Gallery.AvatarView"
xmlns:controls="clr-namespace:AlohaKit.Controls;assembly=AlohaKit"
Title="Avatar">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="SettingsTextStyle" TargetType="Label">
<Setter Property="FontSize" Value="9" />
</Style>
<Style x:Key="SettingsEntryStyle" TargetType="Entry">
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="WidthRequest" Value="80" />
<Setter Property="Margin" Value="6, 0" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- DESCRIPTION -->
<StackLayout
Style="{StaticResource SectionContainerStyle}">
<Label
Text="The Avatar control displays the initials of a person, entity, or group on top of a colored circular background."/>
</StackLayout>
<!-- FEATURES -->
<StackLayout
Grid.Row="1"
BackgroundColor="{AppThemeBinding Light={StaticResource LightBackgroundSecondaryColor}, Dark={StaticResource DarkBackgroundSecondaryColor}}"
Style="{StaticResource SectionContainerStyle}">
<Label
Text="Features"
Style="{StaticResource SectionTitleStyle}"/>
<Label
Text="- Can choose from several predefined sizes."/>
<Label
Text="- Allow to customize the background with a gradient."/>
<Label
Text="- Allow to customize the fill with a gradient."/>
</StackLayout>
<!-- SETTINGS -->
<StackLayout
Grid.Row="2"
Style="{StaticResource SectionContainerStyle}">
<Label
Text="Settings"
Style="{StaticResource SectionTitleStyle}"/>
<StackLayout
Orientation="Horizontal"
Margin="0, 6">
<Label
Text="Fill Start Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="FillStartColorEntry"
Placeholder="Background Color"
Text="#DD5E89"
TextChanged="OnFillStartColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
<Label
Text="Fill End Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="FillEndColorEntry"
Placeholder="Color"
Text="#F7BB97"
TextChanged="OnFillEndColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
</StackLayout>
</StackLayout>
<controls:Avatar
Grid.Row="3"
x:Name="Avatar"
HorizontalOptions="Center"
Name="Javier Suarez"/>
</Grid>
</ContentPage>

Просмотреть файл

@ -0,0 +1,59 @@
namespace AlohaKit.Gallery;
public partial class AvatarView : ContentPage
{
public AvatarView()
{
InitializeComponent();
UpdateBrushes();
}
void OnFillStartColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void OnFillEndColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void UpdateBrushes()
{
var fillStartColor = GetColorFromString(FillStartColorEntry.Text);
var fillEndColor = GetColorFromString(FillEndColorEntry.Text);
if (fillStartColor != null && fillEndColor != null)
{
FillStartColorEntry.BackgroundColor = fillStartColor;
FillEndColorEntry.BackgroundColor = fillEndColor;
Avatar.Fill = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0),
GradientStops = new GradientStopCollection
{
new GradientStop { Color = fillStartColor, Offset = 0 },
new GradientStop { Color = fillEndColor, Offset = 1 }
}
};
}
}
Color GetColorFromString(string value)
{
if (string.IsNullOrEmpty(value))
return null;
try
{
return Color.FromArgb(value[0].Equals('#') ? value : $"#{value}");
}
catch (Exception)
{
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="AlohaKit.Gallery.SliderView"
xmlns:controls="clr-namespace:AlohaKit.Controls;assembly=AlohaKit"
Title="Slider">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="SettingsTextStyle" TargetType="Label">
<Setter Property="FontSize" Value="9" />
</Style>
<Style x:Key="SettingsEntryStyle" TargetType="Entry">
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="WidthRequest" Value="80" />
<Setter Property="Margin" Value="6, 0" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- DESCRIPTION -->
<StackLayout
Style="{StaticResource SectionContainerStyle}">
<Label
Text="Slider is a horizontal bar that can be manipulated by the user to select a double value from a continuous range."/>
</StackLayout>
<!-- FEATURES -->
<StackLayout
Grid.Row="1"
BackgroundColor="{AppThemeBinding Light={StaticResource LightBackgroundSecondaryColor}, Dark={StaticResource DarkBackgroundSecondaryColor}}"
Style="{StaticResource SectionContainerStyle}">
<Label
Text="Features"
Style="{StaticResource SectionTitleStyle}"/>
<Label
Text="- All the colors can be customized supporting gradients."/>
</StackLayout>
<!-- SETTINGS -->
<StackLayout
Grid.Row="2"
Style="{StaticResource SectionContainerStyle}">
<Label
Text="Settings"
Style="{StaticResource SectionTitleStyle}"/>
<StackLayout
Orientation="Horizontal"
Margin="0, 6">
<Label
Text="MinimumBrush Start Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="MinimumBrushStartColorEntry"
Placeholder="MinimumBrush"
Text="#DD5E89"
TextChanged="OnMinimumBrushStartColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
<Label
Text="MinimumBrush End Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="MinimumBrushEndColorEntry"
Placeholder="MinimumBrush"
Text="#F7BB97"
TextChanged="OnMinimumBrushEndColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
</StackLayout>
<StackLayout
Orientation="Horizontal"
Margin="0, 6">
<Label
Text="MaximumBrush Start Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="MaximumBrushStartColorEntry"
Placeholder="MaximumBrush"
Text="#CC2B5E"
TextChanged="OnMaximumBrushStartColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
<Label
Text="MaximumBrush End Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="MaximumBrushEndColorEntry"
Placeholder="Color"
Text="#753A88"
TextChanged="OnMaximumBrushEndColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
</StackLayout>
<StackLayout
Orientation="Horizontal"
Margin="0, 6">
<Label
Text="ThumbBrush Start Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="ThumbBrushStartColorEntry"
Placeholder="ThumbBrush"
Text="#CCCCCC"
TextChanged="OnThumbBrushStartColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
<Label
Text="ThumbBrush End Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="ThumbBrushEndColorEntry"
Placeholder="ThumbBrush"
Text="#BDC3C7"
TextChanged="OnThumbBrushEndColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
</StackLayout>
</StackLayout>
<controls:Slider
Grid.Row="3"
x:Name="Slider" />
</Grid>
</ContentPage>

Просмотреть файл

@ -0,0 +1,119 @@
namespace AlohaKit.Gallery;
public partial class SliderView : ContentPage
{
public SliderView()
{
InitializeComponent();
UpdateBrushes();
}
void OnMinimumBrushStartColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void OnMinimumBrushEndColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void OnMaximumBrushStartColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void OnMaximumBrushEndColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void OnThumbBrushStartColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void OnThumbBrushEndColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void UpdateBrushes()
{
var minimumStartColor = GetColorFromString(MinimumBrushStartColorEntry.Text);
var minimumEndColor = GetColorFromString(MinimumBrushEndColorEntry.Text);
if (minimumStartColor != null && minimumEndColor != null)
{
MinimumBrushStartColorEntry.BackgroundColor = minimumStartColor;
MinimumBrushEndColorEntry.BackgroundColor = minimumEndColor;
Slider.MinimumBrush = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0),
GradientStops = new GradientStopCollection
{
new GradientStop { Color = minimumStartColor, Offset = 0 },
new GradientStop { Color = minimumEndColor, Offset = 1 }
}
};
}
var maximumStartColor = GetColorFromString(MaximumBrushStartColorEntry.Text);
var maximumEndColor = GetColorFromString(MaximumBrushEndColorEntry.Text);
if (maximumStartColor != null && maximumEndColor != null)
{
MaximumBrushStartColorEntry.BackgroundColor = maximumStartColor;
MaximumBrushEndColorEntry.BackgroundColor = maximumEndColor;
Slider.MaximumBrush = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0),
GradientStops = new GradientStopCollection
{
new GradientStop { Color = maximumStartColor, Offset = 0 },
new GradientStop { Color = maximumEndColor, Offset = 1 }
}
};
}
var thumbStartColor = GetColorFromString(ThumbBrushStartColorEntry.Text);
var thumbEndColor = GetColorFromString(ThumbBrushEndColorEntry.Text);
if (thumbStartColor != null && thumbEndColor != null)
{
ThumbBrushStartColorEntry.BackgroundColor = thumbStartColor;
ThumbBrushEndColorEntry.BackgroundColor = thumbEndColor;
Slider.ThumbBrush = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0),
GradientStops = new GradientStopCollection
{
new GradientStop { Color = thumbStartColor, Offset = 0 },
new GradientStop { Color = thumbEndColor, Offset = 1 }
}
};
}
}
Color GetColorFromString(string value)
{
if (string.IsNullOrEmpty(value))
return null;
try
{
return Color.FromArgb(value[0].Equals('#') ? value : $"#{value}");
}
catch (Exception)
{
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,172 @@
namespace AlohaKit.Controls
{
public class Avatar : GraphicsView
{
public Avatar()
{
Drawable = PersonaDrawable = new AvatarDrawable();
}
public AvatarDrawable PersonaDrawable { get; set; }
public static readonly new BindableProperty BackgroundProperty =
BindableProperty.Create(nameof(Background), typeof(Brush), typeof(Avatar), null,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Avatar avatar)
{
avatar.UpdateBackground();
}
});
public new Brush Background
{
get => (Brush)GetValue(BackgroundProperty);
set => SetValue(BackgroundProperty, value);
}
public static readonly BindableProperty FillProperty =
BindableProperty.Create(nameof(Fill), typeof(Brush), typeof(Avatar), new SolidColorBrush(Color.FromArgb("#4967F5")),
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Avatar avatar)
{
avatar.UpdateFill();
}
});
public Brush Fill
{
get => (Brush)GetValue(FillProperty);
set => SetValue(FillProperty, value);
}
public static readonly BindableProperty NameProperty =
BindableProperty.Create(nameof(Name), typeof(string), typeof(Avatar), string.Empty,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Avatar avatar)
{
avatar.UpdateName();
}
});
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
public static readonly BindableProperty TextColorProperty =
BindableProperty.Create(nameof(TextColor), typeof(Color), typeof(Avatar), Colors.White,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Avatar avatar)
{
avatar.UpdateTextColor();
}
});
public Color TextColor
{
get { return (Color)GetValue(TextColorProperty); }
set { SetValue(TextColorProperty, value); }
}
public static readonly BindableProperty AvatarSizeProperty =
BindableProperty.Create(nameof(AvatarSize), typeof(AvatarSize), typeof(Avatar), AvatarSize.Small,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Avatar avatar)
{
avatar.UpdateAvatarSize();
}
});
public AvatarSize AvatarSize
{
get { return (AvatarSize)GetValue(AvatarSizeProperty); }
set { SetValue(AvatarSizeProperty, value); }
}
protected override void OnParentSet()
{
base.OnParentSet();
if (Parent != null)
{
UpdateAvatarSize();
UpdateBackground();
UpdateFill();
UpdateName();
UpdateTextColor();
}
}
void UpdateAvatarSize()
{
HeightRequest = WidthRequest = AvatarSize.GetAvatarSize();
}
void UpdateBackground()
{
if (PersonaDrawable == null)
return;
PersonaDrawable.BackgroundPaint = Background;
Invalidate();
}
void UpdateFill()
{
if (PersonaDrawable == null)
return;
PersonaDrawable.FillPaint = Fill;
Invalidate();
}
void UpdateName()
{
if (PersonaDrawable == null)
return;
PersonaDrawable.Text = GetInitials(Name);
PersonaDrawable.FontSize = AvatarSize.GetInitialsFontSize();
Invalidate();
}
void UpdateTextColor()
{
if (PersonaDrawable == null)
return;
PersonaDrawable.TextColor = TextColor;
Invalidate();
}
string GetInitials(string text)
{
string result = string.Empty;
bool v = true;
for (int i = 0; i < text.Length; i++)
{
if (text[i] == ' ')
v = true;
else if (text[i] != ' ' && v)
{
result += text[i];
v = false;
}
}
return result;
}
}
}

Просмотреть файл

@ -0,0 +1,64 @@
namespace AlohaKit.Controls
{
public class AvatarDrawable : IDrawable
{
public Paint BackgroundPaint { get; set; }
public Paint FillPaint { get; set; }
public string Text { get; set; }
public Color TextColor { get; set; }
public double FontSize { get; set; }
public void Draw(ICanvas canvas, RectF dirtyRect)
{
DrawBackground(canvas, dirtyRect);
DrawFill(canvas, dirtyRect);
DrawInitials(canvas, dirtyRect);
}
public virtual void DrawBackground(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
if (BackgroundPaint != null)
canvas.SetFillPaint(BackgroundPaint, dirtyRect);
canvas.FillRectangle(dirtyRect);
canvas.RestoreState();
}
public virtual void DrawFill(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
if (FillPaint != null)
canvas.SetFillPaint(FillPaint, dirtyRect);
var x = dirtyRect.X;
var y = dirtyRect.Y;
var height = dirtyRect.Height;
var width = dirtyRect.Width;
canvas.FillEllipse(x, y, width, height);
canvas.RestoreState();
}
void DrawInitials(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
canvas.FontColor = TextColor;
canvas.FontSize = (float)FontSize;
var height = dirtyRect.Height;
var width = dirtyRect.Width;
canvas.DrawString(Text, 0, 0, width, height, HorizontalAlignment.Center, VerticalAlignment.Center);
canvas.RestoreState();
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
namespace AlohaKit.Controls
{
public enum AvatarSize
{
Small,
Large,
XXLarge
}
}

Просмотреть файл

@ -0,0 +1,61 @@
namespace AlohaKit.Controls
{
public static class AvatarSizeExtensions
{
public static int GetAvatarSize(this AvatarSize avatarSize)
{
switch (avatarSize)
{
case AvatarSize.Small:
default:
return 48;
case AvatarSize.Large:
return 72;
case AvatarSize.XXLarge:
return 120;
}
}
public static int GetAvatarIndicatorSize(this AvatarSize avatarSize)
{
switch (avatarSize)
{
case AvatarSize.Small:
default:
return 12;
case AvatarSize.Large:
return 20;
case AvatarSize.XXLarge:
return 36;
}
}
public static float GetAvatarIndicatorIconScale(this AvatarSize avatarSize)
{
switch (avatarSize)
{
case AvatarSize.Small:
default:
return 1.0f;
case AvatarSize.Large:
return 1.5f;
case AvatarSize.XXLarge:
return 2.5f;
}
}
public static int GetInitialsFontSize(this AvatarSize avatarSize)
{
switch (avatarSize)
{
case AvatarSize.Small:
default:
return 20;
case AvatarSize.Large:
return 28;
case AvatarSize.XXLarge:
return 42;
}
}
}
}

Просмотреть файл

@ -23,7 +23,7 @@
DrawRatingItem(canvas, dirtyRect, i);
}
}
void DrawBackground(ICanvas canvas, RectF dirtyRect)
public virtual void DrawBackground(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
@ -35,7 +35,7 @@
canvas.RestoreState();
}
void DrawRatingItem(ICanvas canvas, RectF dirtyRect, int index)
public virtual void DrawRatingItem(ICanvas canvas, RectF dirtyRect, int index)
{
canvas.SaveState();

Просмотреть файл

@ -0,0 +1,236 @@
namespace AlohaKit.Controls
{
public class Slider : GraphicsView
{
public Slider()
{
HeightRequest = 20;
WidthRequest = 120;
Drawable = SliderDrawable = new SliderDrawable();
StartInteraction += OnSliderStartInteraction;
DragInteraction += OnSliderDragInteraction;
}
public SliderDrawable SliderDrawable { get; set; }
public static readonly new BindableProperty BackgroundProperty =
BindableProperty.Create(nameof(Background), typeof(Brush), typeof(Button), null,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Slider slider)
{
slider.UpdateBackground();
}
});
public new Brush Background
{
get => (Brush)GetValue(BackgroundProperty);
set => SetValue(BackgroundProperty, value);
}
public static readonly BindableProperty MinimumProperty =
BindableProperty.Create(nameof(Minimum), typeof(double), typeof(Slider), 0d,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Slider slider)
{
slider.UpdateMinimum();
}
});
public double Minimum
{
get => (double)GetValue(MinimumProperty);
set => SetValue(MinimumProperty, value);
}
public static readonly BindableProperty MaximumProperty =
BindableProperty.Create(nameof(Maximum), typeof(double), typeof(Slider), 10d,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Slider slider)
{
slider.UpdateMaximum();
}
});
public double Maximum
{
get => (double)GetValue(MaximumProperty);
set => SetValue(MaximumProperty, value);
}
public static readonly BindableProperty ValueProperty =
BindableProperty.Create(nameof(Value), typeof(double), typeof(Slider), 0d,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Slider slider)
{
slider.UpdateValue();
slider.ValueChanged?.Invoke(slider, new ValueChangedEventArgs((double)oldValue, (double)newValue));
}
});
public double Value
{
get => (double)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
public static readonly BindableProperty MinimumBrushProperty =
BindableProperty.Create(nameof(MinimumBrush), typeof(Brush), typeof(Slider), null,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Slider slider)
{
slider.UpdateMinimumBrush();
}
});
public Brush MinimumBrush
{
get => (Brush)GetValue(MinimumBrushProperty);
set => SetValue(MinimumBrushProperty, value);
}
public static readonly BindableProperty MaximumBrushProperty =
BindableProperty.Create(nameof(MaximumBrush), typeof(Brush), typeof(Slider), null,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Slider slider)
{
slider.UpdateMaximumBrush();
}
});
public Brush MaximumBrush
{
get => (Brush)GetValue(MaximumBrushProperty);
set => SetValue(MaximumBrushProperty, value);
}
public static readonly BindableProperty ThumbBrushProperty =
BindableProperty.Create(nameof(ThumbBrush), typeof(Brush), typeof(Slider), null,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is Slider slider)
{
slider.UpdateThumbBrush();
}
});
public Brush ThumbBrush
{
get => (Brush)GetValue(ThumbBrushProperty);
set => SetValue(ThumbBrushProperty, value);
}
public event EventHandler<ValueChangedEventArgs> ValueChanged;
protected override void OnParentSet()
{
base.OnParentSet();
if(Parent != null)
{
UpdateBackground();
UpdateMinimum();
UpdateMaximum();
UpdateValue();
UpdateMinimumBrush();
UpdateMaximumBrush();
UpdateThumbBrush();
}
}
void UpdateBackground()
{
if (SliderDrawable == null)
return;
SliderDrawable.BackgroundPaint = Background;
Invalidate();
}
void UpdateMinimum()
{
if (SliderDrawable == null)
return;
SliderDrawable.Minimum = Minimum;
Invalidate();
}
void UpdateMaximum()
{
if (SliderDrawable == null)
return;
SliderDrawable.Maximum = Maximum;
Invalidate();
}
void UpdateValue()
{
if (SliderDrawable == null)
return;
SliderDrawable.Value = Value;
Invalidate();
}
void UpdateMinimumBrush()
{
if (SliderDrawable == null)
return;
SliderDrawable.MinimumPaint = MinimumBrush;
Invalidate();
}
void UpdateMaximumBrush()
{
if (SliderDrawable == null)
return;
SliderDrawable.MaximumPaint = MaximumBrush;
Invalidate();
}
void UpdateThumbBrush()
{
if (SliderDrawable == null)
return;
SliderDrawable.ThumbPaint = ThumbBrush;
Invalidate();
}
void OnSliderStartInteraction(object sender, TouchEventArgs args)
{
var touchPoint = args.Touches[0];
UpdateValueFromInteraction(touchPoint);
}
void OnSliderDragInteraction(object sender, TouchEventArgs args)
{
var touchPoint = args.Touches[0];
UpdateValueFromInteraction(touchPoint);
}
void UpdateValueFromInteraction(PointF touchPoint)
{
Value = touchPoint.X * Maximum / Width;
}
}
}

Просмотреть файл

@ -0,0 +1,102 @@
using AlohaKit.Extensions;
namespace AlohaKit.Controls
{
public class SliderDrawable : IDrawable
{
public Paint BackgroundPaint { get; set; }
public double Minimum { get; set; }
public double Maximum { get; set; }
public double Value { get; set; }
public Paint MinimumPaint { get; set; }
public Paint MaximumPaint { get; set; }
public Paint ThumbPaint { get; set; }
public void Draw(ICanvas canvas, RectF dirtyRect)
{
DrawBackground(canvas, dirtyRect);
DrawTrackBackground(canvas, dirtyRect);
DrawTrackProgress(canvas, dirtyRect);
DrawThumb(canvas, dirtyRect);
}
public virtual void DrawBackground(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
if (BackgroundPaint != null)
canvas.SetFillPaint(BackgroundPaint, dirtyRect);
canvas.FillRectangle(dirtyRect);
canvas.RestoreState();
}
public virtual void DrawTrackBackground(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
if(MaximumPaint != null)
canvas.SetFillPaint(MaximumPaint, dirtyRect);
var x = dirtyRect.X;
var width = dirtyRect.Width;
var height = 2;
var y = (float)((dirtyRect.Height - height) / 2);
canvas.FillRoundedRectangle(x, y, width, height, 0);
canvas.RestoreState();
}
public virtual void DrawTrackProgress(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
if (MinimumPaint != null)
canvas.SetFillPaint(MinimumPaint, dirtyRect);
var x = dirtyRect.X;
var value = (Value / Maximum - Minimum).Clamp(0, 1);
var width = (float)(dirtyRect.Width * value);
const float TrackSize = 2f;
var height = TrackSize;
var y = (float)((dirtyRect.Height - height) / 2);
canvas.FillRoundedRectangle(x, y, width, height, 0);
canvas.RestoreState();
}
public virtual void DrawThumb(ICanvas canvas, RectF dirtyRect)
{
const float ThumbSize = 18f;
canvas.SaveState();
var value = (Value / Maximum - Minimum).Clamp(0, 1);
var x = (float)((dirtyRect.Width * value) - (ThumbSize / 2));
if (x <= 0)
x = 0;
if (x >= dirtyRect.Width - ThumbSize)
x = dirtyRect.Width - ThumbSize;
var y = (float)((dirtyRect.Height - ThumbSize) / 2);
if (ThumbPaint != null)
canvas.SetFillPaint(ThumbPaint, dirtyRect);
canvas.FillEllipse(x, y, ThumbSize, ThumbSize);
canvas.RestoreState();
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
namespace AlohaKit.Extensions
{
public static class NumericExtensions
{
public static double Clamp(this double self, double min, double max)
{
if (max < min)
{
return max;
}
else if (self < min)
{
return min;
}
else if (self > max)
{
return max;
}
return self;
}
}
}