Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CheckBox Handlers #432

Merged
merged 12 commits into from
Mar 16, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class CheckBoxRendererBase :
IPlatformElementConfiguration<PlatformConfiguration.Android, CheckBox> _platformElementConfiguration;
CheckBox _checkBox;

[PortHandler]
static int[][] _checkedStates = new int[][]
{
new int[] { AAttribute.StateEnabled, AAttribute.StateChecked },
Expand Down Expand Up @@ -185,6 +186,7 @@ void IOnCheckedChangeListener.OnCheckedChanged(CompoundButton buttonView, bool i
((IElementController)Element).SetValueFromRenderer(CheckBox.IsCheckedProperty, isChecked);
}

[PortHandler]
void UpdateIsChecked()
{
if (Element == null || Control == null)
Expand All @@ -210,6 +212,7 @@ protected virtual ColorStateList GetColorStateList()
return list;
}

[PortHandler]
void UpdateBackgroundColor()
{
if (Element.BackgroundColor == Color.Default)
Expand All @@ -225,6 +228,7 @@ void UpdateBackground()
this.UpdateBackground(background);
}

[PortHandler]
void UpdateOnColor()
{
if (Element == null || Control == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ protected override void OnElementChanged(ElementChangedEventArgs<CheckBox> e)
base.OnElementChanged(e);
}

[PortHandler]
protected virtual void UpdateTintColor()
{
if (Element == null)
Expand All @@ -129,6 +130,7 @@ protected virtual void UpdateTintColor()
Control.CheckBoxTintColor = Element.Color;
}

[PortHandler]
void OnControlCheckedChanged(object sender, EventArgs e)
{
Element.IsChecked = Control.IsChecked;
Expand Down
1 change: 1 addition & 0 deletions src/Compatibility/Core/src/iOS/Renderers/FormsCheckBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS
{
[PortHandler("NativeCheckBox")]
public class FormsCheckBox : UIButton
{
static UIImage _checked;
Expand Down
5 changes: 5 additions & 0 deletions src/Controls/samples/Controls.Sample/Pages/MainPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ void SetupMauiLayout()

verticalStack.Add(horizontalStack);

verticalStack.Add(new CheckBox());
verticalStack.Add(new CheckBox { BackgroundColor = Color.LightPink });
verticalStack.Add(new CheckBox { IsChecked = true, Color = Color.Aquamarine });

verticalStack.Add(new Editor());
verticalStack.Add(new Editor { Text = "Editor" });

Expand All @@ -89,6 +93,7 @@ void SetupMauiLayout()
};

verticalStack.Add(entry);

verticalStack.Add(new Entry { Text = "Entry", TextColor = Color.DarkRed });
verticalStack.Add(new Entry { IsPassword = true, TextColor = Color.Black });
verticalStack.Add(new Entry { IsTextPredictionEnabled = false });
Expand Down
2 changes: 1 addition & 1 deletion src/Controls/src/Core/CheckBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Microsoft.Maui.Controls
{
public class CheckBox : View, IElementConfiguration<CheckBox>, IBorderElement, IColorElement
public partial class CheckBox : View, IElementConfiguration<CheckBox>, IBorderElement, IColorElement
{
readonly Lazy<PlatformConfigurationRegistry<CheckBox>> _platformConfigurationRegistry;
public const string IsCheckedVisualState = "IsChecked";
Expand Down
7 changes: 7 additions & 0 deletions src/Controls/src/Core/HandlerImpl/CheckBox.Impl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Microsoft.Maui.Controls
{
public partial class CheckBox : ICheck
{

}
}
8 changes: 8 additions & 0 deletions src/Core/src/Core/ICheck.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Microsoft.Maui
{
public interface ICheck : IView
{
bool IsChecked { get; set; }
Color Color { get; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove the Color stuff until we have resolved the Brush question?

}
}
57 changes: 57 additions & 0 deletions src/Core/src/Handlers/CheckBox/CheckBoxHandler.Android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Android.Widget;
using AndroidX.AppCompat.Widget;

namespace Microsoft.Maui.Handlers
{
public partial class CheckBoxHandler : AbstractViewHandler<ICheck, AppCompatCheckBox>
{
CheckedChangeListener ChangeListener { get; } = new CheckedChangeListener();

protected override AppCompatCheckBox CreateNativeView()
{
var nativeCheckBox = new AppCompatCheckBox(Context)
{
SoundEffectsEnabled = false
};

nativeCheckBox.SetClipToOutline(true);

return nativeCheckBox;
}

protected override void ConnectHandler(AppCompatCheckBox nativeView)
{
ChangeListener.Handler = this;
nativeView.SetOnCheckedChangeListener(ChangeListener);
}

protected override void DisconnectHandler(AppCompatCheckBox nativeView)
{
ChangeListener.Handler = null;
nativeView.SetOnCheckedChangeListener(null);
}

void OnCheckedChanged(bool isChecked)
{
if (VirtualView != null)
VirtualView.IsChecked = isChecked;
}

internal class CheckedChangeListener : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener
{
public CheckBoxHandler? Handler { get; set; }

public CheckedChangeListener()
{
}

public void OnCheckedChanged(CompoundButton? nativeCheckBox, bool isChecked)
{
if (Handler == null || nativeCheckBox == null)
return;

Handler.OnCheckedChanged(isChecked);
}
}
}
}
9 changes: 9 additions & 0 deletions src/Core/src/Handlers/CheckBox/CheckBoxHandler.Standard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace Microsoft.Maui.Handlers
{
public partial class CheckBoxHandler : AbstractViewHandler<ICheck, object>
{
protected override object CreateNativeView() => throw new NotImplementedException();
}
}
39 changes: 39 additions & 0 deletions src/Core/src/Handlers/CheckBox/CheckBoxHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace Microsoft.Maui.Handlers
{
public partial class CheckBoxHandler
{
public static PropertyMapper<ICheck, CheckBoxHandler> CheckBoxMapper = new PropertyMapper<ICheck, CheckBoxHandler>(ViewHandler.ViewMapper)
{
#if MONOANDROID
[nameof(ICheck.BackgroundColor)] = MapBackgroundColor,
#endif
[nameof(ICheck.IsChecked)] = MapIsChecked,
[nameof(ICheck.Color)] = MapColor
};

public CheckBoxHandler() : base(CheckBoxMapper)
{

}

public CheckBoxHandler(PropertyMapper mapper) : base(mapper ?? CheckBoxMapper)
{

}
#if MONOANDROID
public static void MapBackgroundColor(CheckBoxHandler handler, ICheck check)
{
handler.TypedNativeView?.UpdateBackgroundColor(check);
}
#endif
public static void MapIsChecked(CheckBoxHandler handler, ICheck check)
{
handler.TypedNativeView?.UpdateIsChecked(check);
}

public static void MapColor(CheckBoxHandler handler, ICheck check)
{
handler.TypedNativeView?.UpdateColor(check);
}
}
}
74 changes: 74 additions & 0 deletions src/Core/src/Handlers/CheckBox/CheckBoxHandler.iOS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System;

namespace Microsoft.Maui.Handlers
{
public partial class CheckBoxHandler : AbstractViewHandler<ICheck, NativeCheckBox>
{
protected virtual float MinimumSize => 44f;

protected override NativeCheckBox CreateNativeView()
{
return new NativeCheckBox
{
MinimumViewSize = MinimumSize
};
}

protected override void ConnectHandler(NativeCheckBox nativeView)
{
base.ConnectHandler(nativeView);

nativeView.CheckedChanged += OnCheckedChanged;
}

protected override void DisconnectHandler(NativeCheckBox nativeView)
{
base.DisconnectHandler(nativeView);

nativeView.CheckedChanged -= OnCheckedChanged;
}

public override Size GetDesiredSize(double widthConstraint, double heightConstraint)
{
var size = base.GetDesiredSize(widthConstraint, heightConstraint);

var set = false;

var width = widthConstraint;
var height = heightConstraint;

if (size.Width == 0)
{
if (widthConstraint <= 0 || double.IsInfinity(widthConstraint))
{
width = MinimumSize;
set = true;
}
}

if (size.Height == 0)
{
if (heightConstraint <= 0 || double.IsInfinity(heightConstraint))
{
height = MinimumSize;
set = true;
}
}

if (set)
{
size = new Size(width, height);
}

return size;
}

void OnCheckedChanged(object? sender, EventArgs e)
{
if (sender is NativeCheckBox nativeView && VirtualView != null)
{
VirtualView.IsChecked = nativeView.IsChecked;
}
}
}
}
1 change: 1 addition & 0 deletions src/Core/src/Hosting/AppHostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public static IAppHostBuilder UseMauiHandlers(this IAppHostBuilder builder)
builder.RegisterHandlers(new Dictionary<Type, Type>
{
{ typeof(IButton), typeof(ButtonHandler) },
{ typeof(ICheck), typeof(CheckBoxHandler) },
{ typeof(IEditor), typeof(EditorHandler) },
{ typeof(IEntry), typeof(EntryHandler) },
{ typeof(ILayout), typeof(LayoutHandler) },
Expand Down
57 changes: 57 additions & 0 deletions src/Core/src/Platform/Android/CheckBoxExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Android.Content.Res;
using Android.Graphics;
using AndroidX.AppCompat.Widget;
using AndroidX.Core.Widget;
using AAttribute = Android.Resource.Attribute;
using AColor = Android.Graphics.Color;
using XColor = Microsoft.Maui.Color;

namespace Microsoft.Maui
{
public static class CheckBoxExtensions
{
static readonly int[][] CheckedStates = new int[][]
{
new int[] { AAttribute.StateEnabled, AAttribute.StateChecked },
new int[] { AAttribute.StateEnabled, -AAttribute.StateChecked },
new int[] { -AAttribute.StateEnabled, AAttribute.StateChecked },
new int[] { -AAttribute.StateEnabled, -AAttribute.StatePressed },
};

public static void UpdateBackgroundColor(this AppCompatCheckBox nativeCheckBox, ICheck check)
{
if (check.BackgroundColor == XColor.Default)
nativeCheckBox.SetBackgroundColor(AColor.Transparent);
else
nativeCheckBox.SetBackgroundColor(check.BackgroundColor.ToNative());
}

public static void UpdateIsChecked(this AppCompatCheckBox nativeCheckBox, ICheck check)
{
nativeCheckBox.Checked = check.IsChecked;
}

public static void UpdateColor(this AppCompatCheckBox nativeCheckBox, ICheck check)
{
// TODO: Delete when implementing the logic to set the system accent color.
XColor accent = XColor.FromHex("#ff33b5e5");

var tintColor = check.Color == XColor.Default ? accent.ToNative() : check.Color.ToNative();

var tintList = new ColorStateList(
CheckedStates,
new int[]
{
tintColor,
tintColor,
tintColor,
tintColor
});

var tintMode = PorterDuff.Mode.SrcIn;

CompoundButtonCompat.SetButtonTintList(nativeCheckBox, tintList);
CompoundButtonCompat.SetButtonTintMode(nativeCheckBox, tintMode);
}
}
}
14 changes: 10 additions & 4 deletions src/Core/src/Platform/Android/ViewExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
using System;
using Android.Content.Res;
using Android.Graphics.Drawables;
using Microsoft.Maui;
using AView = Android.Views.View;

namespace Microsoft.Maui
Expand All @@ -24,6 +20,16 @@ public static void UpdateBackgroundColor(this AView nativeView, IView view)
nativeView?.SetBackgroundColor(backgroundColor.ToNative());
}

public static bool GetClipToOutline(this AView view)
{
return view.ClipToOutline;
}

public static void SetClipToOutline(this AView view, bool value)
{
view.ClipToOutline = value;
}

public static void UpdateAutomationId(this AView nativeView, IView view)
{
if (AutomationTagId == DefaultAutomationTagId)
Expand Down
15 changes: 15 additions & 0 deletions src/Core/src/Platform/Standard/CheckBoxExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Microsoft.Maui
{
public static class CheckBoxExtensions
{
public static void UpdateIsChecked(this object nothing, ICheck check)
{

}

public static void UpdateColor(this object nothing, ICheck check)
{

}
}
}
Loading