Skip to content

Commit

Permalink
Picker Handlers (#433)
Browse files Browse the repository at this point in the history
* PickerHandlers

* Nullability fixes

* Updated Picker device tests

* New things in the tests!

* Removed unnecessary Android Api level validation

* Added Picker Items null validation in iOS PickerHandler

* Moved Picker Handler tests between different classes

* Renamed NativePicker to MauiPicker

* Removed unused code from iOS PickerExtensions

* Fix build error

* Fix build error

* Remove duplicate class

Co-authored-by: Matthew Leibowitz <mattleibow@live.com>
Co-authored-by: E.Z. Hart <hartez@gmail.com>
  • Loading branch information
3 people committed Mar 17, 2021
1 parent d7f7909 commit e0a563d
Show file tree
Hide file tree
Showing 24 changed files with 799 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ protected override void OnFocusChangeRequested(object sender, VisualElement.Focu
}
}

[PortHandler("Partially ported, still missing code related to TitleColor, etc.")]
void IPickerRenderer.OnClick()
{
Picker model = Element;
Expand Down Expand Up @@ -168,6 +169,7 @@ protected void UpdateCharacterSpacing()
}
}

[PortHandler("Partially ported, still missing code related to TitleColor, etc.")]
void UpdatePicker()
{
UpdatePlaceHolderText();
Expand Down
7 changes: 7 additions & 0 deletions src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS
{
[PortHandler]
internal class ReadOnlyField : NoCaretField
{
readonly HashSet<string> enableActions;
Expand All @@ -32,6 +33,7 @@ public PickerRenderer()

}

[PortHandler]
protected override UITextField CreateNativeControl()
{
return new ReadOnlyField { BorderStyle = UITextBorderStyle.RoundedRect };
Expand All @@ -56,6 +58,8 @@ public PickerRendererBase()
}

protected abstract override TControl CreateNativeControl();

[PortHandler("Partially ported, still missing code related to TitleColor, etc.")]
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
if (e.OldElement != null)
Expand Down Expand Up @@ -231,6 +235,7 @@ protected internal virtual void UpdatePlaceholder()
protected virtual void UpdateAttributedPlaceholder(NSAttributedString nsAttributedString) =>
Control.AttributedPlaceholder = nsAttributedString;

[PortHandler]
void UpdatePicker()
{
var selectedIndex = Element.SelectedIndex;
Expand Down Expand Up @@ -266,6 +271,7 @@ void UpdatePickerNativeSize(string oldText)
((IVisualElementController)Element).NativeSizeChanged();
}

[PortHandler]
void UpdatePickerSelectedIndex(int formsIndex)
{
var source = (PickerSource)_picker.Model;
Expand Down Expand Up @@ -334,6 +340,7 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}

[PortHandler]
class PickerSource : UIPickerViewModel
{
PickerRendererBase<TControl> _renderer;
Expand Down
19 changes: 19 additions & 0 deletions src/Controls/samples/Controls.Sample/Pages/MainPage.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using Maui.Controls.Sample.ViewModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui;
Expand Down Expand Up @@ -113,6 +115,23 @@ void SetupMauiLayout()
placeholderSearchBar.Placeholder = "Placeholder";
verticalStack.Add(placeholderSearchBar);


var monkeyList = new List<string>
{
"Baboon",
"Capuchin Monkey",
"Blue Monkey",
"Squirrel Monkey",
"Golden Lion Tamarin",
"Howler Monkey",
"Japanese Macaque"
};

var picker = new Picker { Title = "Select a monkey" };

picker.ItemsSource = monkeyList;
verticalStack.Add(picker);

verticalStack.Add(new Slider());

verticalStack.Add(new Stepper());
Expand Down
7 changes: 7 additions & 0 deletions src/Controls/src/Core/HandlerImpl/Picker.Impl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Microsoft.Maui.Controls
{
public partial class Picker : IPicker
{

}
}
2 changes: 1 addition & 1 deletion src/Controls/src/Core/Picker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Microsoft.Maui.Controls
{
public class Picker : View, IFontElement, ITextElement, ITextAlignmentElement, IElementConfiguration<Picker>
public partial class Picker : View, IFontElement, ITextElement, ITextAlignmentElement, IElementConfiguration<Picker>
{
public static readonly BindableProperty TextColorProperty = TextElement.TextColorProperty;

Expand Down
14 changes: 14 additions & 0 deletions src/Core/src/Core/IPicker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Collections;
using System.Collections.Generic;

namespace Microsoft.Maui
{
public interface IPicker : IView
{
string Title { get; }
IList<string> Items { get; }
IList ItemsSource { get; }
int SelectedIndex { get; set; }
object? SelectedItem { get; set; }
}
}
112 changes: 112 additions & 0 deletions src/Core/src/Handlers/Picker/PickerHandler.Android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using System.Collections.Specialized;
using System.Linq;
using Android.App;
using AResource = Android.Resource;

namespace Microsoft.Maui.Handlers
{
public partial class PickerHandler : AbstractViewHandler<IPicker, MauiPicker>
{
AlertDialog? _dialog;

protected override MauiPicker CreateNativeView() =>
new MauiPicker(Context);

protected override void ConnectHandler(MauiPicker nativeView)
{
nativeView.FocusChange += OnFocusChange;
nativeView.Click += OnClick;

if (VirtualView != null && VirtualView.Items is INotifyCollectionChanged notifyCollection)
notifyCollection.CollectionChanged += OnCollectionChanged;

base.ConnectHandler(nativeView);
}

protected override void DisconnectHandler(MauiPicker nativeView)
{
nativeView.FocusChange -= OnFocusChange;
nativeView.Click -= OnClick;

if (VirtualView != null && VirtualView.Items is INotifyCollectionChanged notifyCollection)
notifyCollection.CollectionChanged -= OnCollectionChanged;

base.DisconnectHandler(nativeView);
}
public static void MapTitle(PickerHandler handler, IPicker picker)
{
handler.TypedNativeView?.UpdateTitle(picker);
}

public static void MapSelectedIndex(PickerHandler handler, IPicker picker)
{
handler.TypedNativeView?.UpdateSelectedIndex(picker);
}

void OnFocusChange(object? sender, global::Android.Views.View.FocusChangeEventArgs e)
{
if (TypedNativeView == null)
return;

if (e.HasFocus)
{
if (TypedNativeView.Clickable)
TypedNativeView.CallOnClick();
else
OnClick(TypedNativeView, EventArgs.Empty);
}
else if (_dialog != null)
{
_dialog.Hide();
TypedNativeView.ClearFocus();
_dialog = null;
}
}

void OnClick(object? sender, EventArgs e)
{
if (_dialog == null && VirtualView != null)
{
using (var builder = new AlertDialog.Builder(Context))
{
builder.SetTitle(VirtualView.Title ?? string.Empty);

string[] items = VirtualView.Items.ToArray();

builder.SetItems(items, (s, e) =>
{
var selectedIndex = e.Which;
VirtualView.SelectedIndex = selectedIndex;
TypedNativeView?.UpdatePicker(VirtualView);
});

builder.SetNegativeButton(AResource.String.Cancel, (o, args) => { });

_dialog = builder.Create();
}

if (_dialog == null)
return;

_dialog.SetCanceledOnTouchOutside(true);

_dialog.DismissEvent += (sender, args) =>
{
_dialog.Dispose();
_dialog = null;
};

_dialog.Show();
}
}

void OnCollectionChanged(object? sender, EventArgs e)
{
if (VirtualView == null || TypedNativeView == null)
return;

TypedNativeView.UpdatePicker(VirtualView);
}
}
}
12 changes: 12 additions & 0 deletions src/Core/src/Handlers/Picker/PickerHandler.Standard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace Microsoft.Maui.Handlers
{
public partial class PickerHandler : AbstractViewHandler<IPicker, object>
{
protected override object CreateNativeView() => throw new NotImplementedException();

public static void MapTitle(PickerHandler handler, IPicker view) { }
public static void MapSelectedIndex(PickerHandler handler, IPicker view) { }
}
}
21 changes: 21 additions & 0 deletions src/Core/src/Handlers/Picker/PickerHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Microsoft.Maui.Handlers
{
public partial class PickerHandler
{
public static PropertyMapper<IPicker, PickerHandler> PickerMapper = new PropertyMapper<IPicker, PickerHandler>(ViewHandler.ViewMapper)
{
[nameof(IPicker.Title)] = MapTitle,
[nameof(IPicker.SelectedIndex)] = MapSelectedIndex
};

public PickerHandler() : base(PickerMapper)
{

}

public PickerHandler(PropertyMapper mapper) : base(mapper)
{

}
}
}
Loading

0 comments on commit e0a563d

Please sign in to comment.