Skip to content

Commit 2874337

Browse files
committed
Adapt XF Checkbox to v4
1 parent c1e844b commit 2874337

File tree

4 files changed

+134
-95
lines changed

4 files changed

+134
-95
lines changed

sandbox/SandboxMAUI/Pages/CheckBoxPage.xaml.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System;
2-
using Microsoft.Maui.Controls;
3-
using Microsoft.Maui.Graphics;
1+
using InputKit.Shared.Helpers;
42
using CheckBox = InputKit.Shared.Controls.CheckBox;
53

64
namespace SandboxMAUI.Pages;
@@ -27,6 +25,7 @@ private void Button_Clicked(object sender, EventArgs e)
2725
if(sender is Button button)
2826
{
2927
button.BackgroundColor = color;
28+
button.TextColor = color.ToSurfaceColor();
3029
}
3130
}
3231
}

sandbox/SandboxXF/SandboxXF/Views/CheckBoxesPage.xaml

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@
1111
Padding="25"
1212
Spacing="15">
1313

14-
<input:CheckBox Text="Option 0 with Box Type" Type="Box" LabelPosition="After"/>
15-
<input:CheckBox Text="Option 1 with Check Type" Type="Check"/>
16-
<input:CheckBox Text="Option 2 wity Cross Type" Type="Cross"/>
17-
<input:CheckBox Text="Option 3 with Custom Type" Type="Custom" CustomIcon="ic_account_balance_black"/>
18-
<input:CheckBox Text="Option 4 with Material Type" Type="Material"/>
19-
<input:CheckBox Text="Option 5 with Star Type" Type="Star"/>
20-
<input:CheckBox Text="Option 6 (Position)" Type="Check" LabelPosition="Before"/>
14+
<Button Text="Randomize colors" Clicked="Button_Clicked" />
15+
<BoxView Color="{AppThemeBinding Dark=White, Light=Black}" HeightRequest="1" HorizontalOptions="Fill" Margin="5,10" />
16+
17+
<input:CheckBox Text="Option 0 Plain Checkbox" />
18+
<input:CheckBox Text="Option 1 with Filled Type" Type="Filled" />
19+
<input:CheckBox Text="Option 2 with Material Type" Type="Material" />
20+
<input:CheckBox Text="Option 2 with Square Shape" IconGeometry="{x:Static input:PredefinedShapes.Square}" />
21+
<input:CheckBox Text="Option 3 with Line Shape" IconGeometry="{x:Static input:PredefinedShapes.Line}" />
22+
<input:CheckBox Text="Option 3 with Line Shape with Material Type" Type="Material" IconGeometry="{x:Static input:PredefinedShapes.Line}" />
23+
<input:CheckBox Text="Option 3 with Custom Type (X)" Type="Custom" IconGeometry="M17.705 7.705l-1.41-1.41L12 10.59 7.705 6.295l-1.41 1.41L10.59 12l-4.295 4.295 1.41 1.41L12 13.41l4.295 4.295 1.41-1.41L13.41 12l4.295-4.295z"/>
24+
<input:CheckBox Text="Option 5 with Material Custom Type (X)" Type="Material" IconGeometry="M17.705 7.705l-1.41-1.41L12 10.59 7.705 6.295l-1.41 1.41L10.59 12l-4.295 4.295 1.41 1.41L12 13.41l4.295 4.295 1.41-1.41L13.41 12l4.295-4.295z"/>
25+
<input:CheckBox Text="Option 6 (Position)" Type="Regular" LabelPosition="Before"/>
2126

2227
</StackLayout>
2328

sandbox/SandboxXF/SandboxXF/Views/CheckBoxesPage.xaml.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using Plugin.InputKit.Shared.Helpers;
2+
using System;
23

34
using Xamarin.Forms;
45
using Xamarin.Forms.Xaml;
@@ -7,12 +8,12 @@
78
namespace SandboxXF.Views
89
{
910
[XamlCompilation(XamlCompilationOptions.Compile)]
10-
public partial class CheckBoxesPage : ContentPage
11-
{
11+
public partial class CheckBoxesPage : ContentPage
12+
{
1213
static readonly Random rnd = new Random();
13-
public CheckBoxesPage()
14-
{
15-
InitializeComponent ();
14+
public CheckBoxesPage()
15+
{
16+
InitializeComponent();
1617
}
1718

1819
private void Button_Clicked(object sender, EventArgs e)
@@ -26,6 +27,12 @@ private void Button_Clicked(object sender, EventArgs e)
2627
chk.Color = color;
2728
}
2829
}
30+
31+
if (sender is Button button)
32+
{
33+
button.BackgroundColor = color;
34+
button.TextColor = color.ToSurfaceColor();
35+
}
2936
}
3037
}
3138
}

src/Xamarin.Forms.InputKit/Shared/Controls/CheckBox.cs

Lines changed: 107 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using Plugin.InputKit.Shared.Helpers;
44
using Plugin.InputKit.Shared.Layouts;
55
using System;
6-
using System.Runtime.CompilerServices;
76
using System.Windows.Input;
87
using Xamarin.Forms;
8+
using Xamarin.Forms.Shapes;
9+
using Rectangle = Xamarin.Forms.Shapes.Rectangle;
910

1011
namespace Plugin.InputKit.Shared.Controls
1112
{
@@ -22,25 +23,46 @@ public partial class CheckBox : StatefulStackLayout, IValidatable
2223
{
2324
BackgroundColor = Color.Transparent,
2425
Color = InputKitOptions.GetAccentColor(),
25-
BorderColor = Color.Black,
26+
BorderColor = Application.Current.RequestedTheme == OSAppTheme.Dark ? Color.WhiteSmoke : Color.Black,
2627
TextColor = (Color)Label.TextColorProperty.DefaultValue,
2728
Size = 25,
28-
CornerRadius = 4,
29+
CornerRadius = 2,
2930
FontSize = 14,
3031
LabelPosition = LabelPosition.After
3132
};
3233

3334
#region Constants
34-
public const string RESOURCE_CHECK = "Plugin.InputKit.Shared.Resources.check.png";
35-
public const string RESOURCE_CROSS = "Plugin.InputKit.Shared.Resources.cross.png";
36-
public const string RESOURCE_STAR = "Plugin.InputKit.Shared.Resources.star.png";
35+
internal const double CHECK_SIZE_RATIO = .65;
3736
#endregion
3837

3938
#region Fields
40-
protected internal Frame frmBackground = new Frame { Padding = 0, CornerRadius = GlobalSetting.CornerRadius, InputTransparent = true, HeightRequest = GlobalSetting.Size, WidthRequest = GlobalSetting.Size, BackgroundColor = GlobalSetting.BackgroundColor, MinimumWidthRequest = 35, BorderColor = GlobalSetting.BorderColor, VerticalOptions = LayoutOptions.CenterAndExpand, HasShadow = false };
41-
protected internal BoxView boxSelected = new BoxView { IsVisible = false, HeightRequest = GlobalSetting.Size * .60, WidthRequest = GlobalSetting.Size * .60, Color = GlobalSetting.Color, VerticalOptions = LayoutOptions.CenterAndExpand, HorizontalOptions = LayoutOptions.Center };
42-
protected internal IconView imgSelected = new IconView { Source = ImageSource.FromResource(RESOURCE_CHECK), FillColor = GlobalSetting.Color, VerticalOptions = LayoutOptions.CenterAndExpand, HorizontalOptions = LayoutOptions.Center, IsVisible = false };
43-
internal Label lblOption = new Label { VerticalOptions = LayoutOptions.CenterAndExpand, FontSize = GlobalSetting.FontSize, TextColor = GlobalSetting.TextColor, FontFamily = GlobalSetting.FontFamily, IsVisible = false };
39+
protected internal Grid IconLayout;
40+
protected Rectangle outlineBox = new Rectangle
41+
{
42+
Fill = GlobalSetting.BackgroundColor.ToBrush(),
43+
Stroke = GlobalSetting.BorderColor.ToBrush(),
44+
StrokeThickness = 2,
45+
WidthRequest = GlobalSetting.Size,
46+
HeightRequest = GlobalSetting.Size,
47+
RadiusX = GlobalSetting.CornerRadius,
48+
};
49+
protected Path selectedIcon = new Path
50+
{
51+
Fill = GlobalSetting.Color.ToBrush(),
52+
Aspect = Stretch.Uniform,
53+
HeightRequest = GlobalSetting.Size,
54+
WidthRequest = GlobalSetting.Size,
55+
Scale = 0,
56+
};
57+
protected internal Label lblOption = new Label
58+
{
59+
VerticalOptions = LayoutOptions.Center,
60+
HorizontalOptions = LayoutOptions.Start,
61+
FontSize = GlobalSetting.FontSize,
62+
TextColor = GlobalSetting.TextColor,
63+
FontFamily = GlobalSetting.FontFamily,
64+
IsVisible = false
65+
};
4466
private CheckType _type = CheckType.Box;
4567
private bool _isEnabled;
4668
#endregion
@@ -53,18 +75,27 @@ public CheckBox()
5375
{
5476
InitVisualStates();
5577
Orientation = StackOrientation.Horizontal;
56-
Padding = new Thickness(0, 10);
5778
Spacing = 10;
58-
frmBackground.Content = boxSelected;
59-
ApplyLabelPosition(LabelPosition);
79+
Padding = new Thickness(0, 10);
6080
ApplyIsCheckedAction = ApplyIsChecked;
6181
ApplyIsPressedAction = ApplyIsPressed;
82+
83+
IconLayout = new Grid
84+
{
85+
Children =
86+
{
87+
outlineBox,
88+
selectedIcon
89+
}
90+
};
91+
92+
ApplyLabelPosition(LabelPosition);
93+
UpdateType();
94+
UpdateShape();
6295
GestureRecognizers.Add(new TapGestureRecognizer
6396
{
6497
Command = new Command(() => { if (IsDisabled) return; IsChecked = !IsChecked; ExecuteCommand(); CheckChanged?.Invoke(this, new EventArgs()); ValidationChanged?.Invoke(this, new EventArgs()); }),
6598
});
66-
67-
imgSelected.WidthRequest = 15;
6899
}
69100

70101
/// <summary>
@@ -159,17 +190,17 @@ public Color Color
159190
/// <summary>
160191
/// Which icon will be shown when checkbox is checked
161192
/// </summary>
162-
public CheckType Type { get => _type; set { _type = value; UpdateType(value); } }
193+
public CheckType Type { get => _type; set { _type = value; UpdateType(); } }
163194

164195
/// <summary>
165196
/// Size of Checkbox
166197
/// </summary>
167-
public double BoxSize { get => frmBackground.Width; }
198+
public double BoxSize { get => outlineBox.Width; }
168199

169200
/// <summary>
170201
/// SizeRequest of CheckBox
171202
/// </summary>
172-
public double BoxSizeRequest { get => frmBackground.WidthRequest; set => SetBoxSize(value); }
203+
public double BoxSizeRequest { get => outlineBox.WidthRequest; set => SetBoxSize(value); }
173204

174205
/// <summary>
175206
/// Fontsize of Checkbox text
@@ -200,7 +231,11 @@ public Color Color
200231
/// </summary>
201232
public string FontFamily { get => (string)GetValue(FontFamilyProperty); set => SetValue(FontFamilyProperty, value); }
202233

203-
public ImageSource CustomIcon { get => (ImageSource)GetValue(CustomIconProperty); set => SetValue(CustomIconProperty, value); }
234+
[Obsolete("This option is removed. Use CustomIconGeometry")]
235+
public ImageSource CustomIcon { get => default; set { } }
236+
237+
[TypeConverter(typeof(PathGeometryConverter))]
238+
public Geometry IconGeometry { get => (Geometry)GetValue(IconGeometryProperty); set => SetValue(IconGeometryProperty, value); }
204239

205240
public bool IsPressed { get; set; }
206241
/// <summary>
@@ -232,9 +267,9 @@ public LabelPosition LabelPosition
232267
public static readonly BindableProperty TextFontSizeProperty = BindableProperty.Create(nameof(TextFontSize), typeof(double), typeof(CheckBox), GlobalSetting.FontSize, propertyChanged: (bo, ov, nv) => (bo as CheckBox).TextFontSize = (double)nv);
233268
public static readonly BindableProperty BorderColorProperty = BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(CheckBox), GlobalSetting.BorderColor, propertyChanged: (bo, ov, nv) => (bo as CheckBox).UpdateBorderColor());
234269
public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create(nameof(FontFamily), typeof(string), typeof(CheckBox), Label.FontFamilyProperty.DefaultValue, propertyChanged: (bo, ov, nv) => (bo as CheckBox).UpdateFontFamily(nv?.ToString()));
235-
public static readonly BindableProperty CustomIconProperty = BindableProperty.Create(nameof(CustomIcon), typeof(ImageSource), typeof(CheckBox), default(ImageSource), propertyChanged: (bo, ov, nv) => (bo as CheckBox).UpdateType((bo as CheckBox).Type));
270+
public static readonly BindableProperty IconGeometryProperty = BindableProperty.Create(nameof(IconGeometry), typeof(Geometry), typeof(CheckBox), defaultValue: PredefinedShapes.Check, propertyChanged: (bo, ov, nv) => (bo as CheckBox).UpdateShape());
236271
public static readonly BindableProperty IsPressedProperty = BindableProperty.Create(nameof(IsPressed), typeof(bool), typeof(CheckBox), propertyChanged: (bo, ov, nv) => (bo as CheckBox).ApplyIsPressedAction(bo as CheckBox, (bool)nv));
237-
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(CheckBox), GlobalSetting.CornerRadius, propertyChanged: (bo, ov, nv) => (bo as CheckBox).frmBackground.CornerRadius = (float)nv);
272+
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(CheckBox), GlobalSetting.CornerRadius, propertyChanged: (bo, ov, nv) => (bo as CheckBox).outlineBox.RadiusX = (float)nv);
238273
public static readonly BindableProperty LabelPositionProperty = BindableProperty.Create(
239274
propertyName: nameof(LabelPosition), declaringType: typeof(CheckBox),
240275
returnType: typeof(LabelPosition), defaultBindingMode: BindingMode.TwoWay,
@@ -250,14 +285,14 @@ void ApplyLabelPosition(LabelPosition position)
250285
if (position == LabelPosition.After)
251286
{
252287
lblOption.HorizontalOptions = LayoutOptions.Start;
253-
Children.Add(frmBackground);
288+
Children.Add(IconLayout);
254289
Children.Add(lblOption);
255290
}
256291
else
257292
{
258-
lblOption.HorizontalOptions = LayoutOptions.StartAndExpand;
293+
lblOption.HorizontalOptions = LayoutOptions.FillAndExpand;
259294
Children.Add(lblOption);
260-
Children.Add(frmBackground);
295+
Children.Add(IconLayout);
261296
}
262297
}
263298

@@ -272,24 +307,34 @@ void UpdateBoxBackground()
272307
if (Type == CheckType.Material)
273308
return;
274309

275-
frmBackground.BackgroundColor = BoxBackgroundColor;
310+
outlineBox.Fill = BoxBackgroundColor.ToBrush();
276311
}
277312

278313
void UpdateColors()
279314
{
280-
boxSelected.Color = Color;
315+
//selectedIcon.Fill = Color;
281316

282-
if (Type == CheckType.Material)
283-
{
284-
frmBackground.BorderColor = Color;
285-
frmBackground.BackgroundColor = IsChecked ? Color : Color.Transparent;
286-
imgSelected.FillColor = Color.ToSurfaceColor();
287-
}
288-
else
317+
switch (Type)
289318
{
290-
frmBackground.BorderColor = IsChecked ? Color : BorderColor;
291-
frmBackground.BackgroundColor = BoxBackgroundColor;
292-
imgSelected.FillColor = IconColor == Color.Transparent ? Color : IconColor;
319+
case CheckType.Regular:
320+
outlineBox.Stroke = IsChecked ? Color.ToBrush() : BorderColor.ToBrush();
321+
outlineBox.Fill = BoxBackgroundColor.ToBrush();
322+
selectedIcon.Fill = IconColor == Color.Transparent ? Color.ToBrush() : IconColor.ToBrush();
323+
break;
324+
case CheckType.Filled:
325+
outlineBox.Fill = IsChecked ? BorderColor.ToBrush() : Color.Transparent.ToBrush();
326+
selectedIcon.Fill = IsChecked ? Color.ToBrush() : Color.Transparent.ToBrush();
327+
break;
328+
case CheckType.Material:
329+
outlineBox.Stroke = Color.ToBrush();
330+
outlineBox.Fill = IsChecked ? Color.ToBrush() : Color.Transparent.ToBrush();
331+
selectedIcon.Fill = Color.ToSurfaceColor().ToBrush();
332+
break;
333+
default:
334+
outlineBox.Stroke = IsChecked ? Color.ToBrush() : BorderColor.ToBrush();
335+
outlineBox.Fill = BoxBackgroundColor.ToBrush();
336+
selectedIcon.Fill = IconColor == Color.Transparent ? Color.ToBrush() : IconColor.ToBrush();
337+
break;
293338
}
294339
}
295340

@@ -298,51 +343,24 @@ void UpdateBorderColor()
298343
if (Type == CheckType.Material)
299344
return;
300345

301-
frmBackground.BorderColor = BorderColor;
346+
outlineBox.Stroke = BorderColor.ToBrush();
302347
}
303348

304-
void SetBoxSize(double value)
349+
void SetBoxSize(double size)
305350
{
306-
frmBackground.WidthRequest = value;
307-
frmBackground.HeightRequest = value;
308-
boxSelected.WidthRequest = value * .6; //old value 0.72
309-
boxSelected.HeightRequest = value * 0.6;
310-
//lblSelected.FontSize = value * 0.72; //old value 0.76 //TODO: Do something to resizing
311-
312-
// TODO: Refactor after MAUI update
313-
(this.Children[0] as View).MinimumWidthRequest = value * 1.4;
351+
outlineBox.HeightRequest = size;
352+
outlineBox.WidthRequest = size;
353+
//selectedIcon.MaximumHeightRequest = size * CHECK_SIZE_RATIO;
354+
//selectedIcon.MaximumWidthRequest = size * CHECK_SIZE_RATIO;
314355
}
315356

316-
void UpdateType(CheckType _Type)
357+
void UpdateShape()
317358
{
318-
switch (_Type)
319-
{
320-
case CheckType.Box:
321-
frmBackground.Content = boxSelected;
322-
break;
323-
case CheckType.Check:
324-
imgSelected.Source = ImageSource.FromResource(RESOURCE_CHECK);
325-
frmBackground.Content = imgSelected;
326-
break;
327-
case CheckType.Cross:
328-
imgSelected.Source = ImageSource.FromResource(RESOURCE_CROSS);
329-
frmBackground.Content = imgSelected;
330-
break;
331-
case CheckType.Star:
332-
imgSelected.Source = ImageSource.FromResource(RESOURCE_STAR);
333-
frmBackground.Content = imgSelected;
334-
break;
335-
case CheckType.Material:
336-
imgSelected.Source = ImageSource.FromResource(RESOURCE_CHECK);
337-
frmBackground.CornerRadius = 5;
338-
frmBackground.Content = imgSelected;
339-
break;
340-
case CheckType.Custom:
341-
imgSelected.Source = CustomIcon;
342-
frmBackground.Content = imgSelected;
343-
break;
344-
}
359+
selectedIcon.Data = IconGeometry;
360+
}
345361

362+
void UpdateType()
363+
{
346364
UpdateColors();
347365
}
348366

@@ -390,27 +408,37 @@ public void DisplayValidation()
390408
{
391409

392410
}
411+
393412
public static void ApplyIsChecked(CheckBox checkBox, bool isChecked)
394413
{
395-
checkBox.frmBackground.Content.IsVisible = isChecked;
414+
checkBox.selectedIcon.ScaleTo(isChecked ? CHECK_SIZE_RATIO : 0, 160);
415+
396416
checkBox.UpdateColors();
397417
}
418+
398419
public static async void ApplyIsPressed(CheckBox checkBox, bool isPressed)
399420
{
400-
await checkBox.frmBackground.ScaleTo(isPressed ? .8 : 1, 50, Easing.BounceIn);
401-
var radiusVal = isPressed ? checkBox.frmBackground.CornerRadius * 2f : checkBox.CornerRadius;
402-
checkBox.frmBackground.CornerRadius = radiusVal;
421+
await checkBox.outlineBox.ScaleTo(isPressed ? .8 : 1, 50, Easing.BounceIn);
422+
var radiusVal = isPressed ? checkBox.outlineBox.RadiusX * 2f : checkBox.CornerRadius;
423+
checkBox.outlineBox.RadiusX = radiusVal;
403424
}
404425
#endregion
405426

406427
public enum CheckType
407428
{
429+
[Obsolete("This option is removed. Use IconGeometry instead.")]
408430
Box,
431+
[Obsolete("This option is removed. Use IconGeometry instead")]
409432
Check,
433+
[Obsolete("This option is removed. Use IconGeometry instead")]
410434
Cross,
435+
[Obsolete("This option is removed. Use IconGeometry instead")]
411436
Star,
437+
[Obsolete("This option is removed. Use IconGeometry instead")]
438+
Custom = 90,
439+
Regular,
440+
Filled,
412441
Material,
413-
Custom = 90
414442
}
415443
}
416444
}

0 commit comments

Comments
 (0)