summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs165
1 files changed, 165 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs
new file mode 100644
index 00000000..b9114d22
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs
@@ -0,0 +1,165 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using Android.App;
+using Android.Views;
+using Android.Widget;
+using ADatePicker = Android.Widget.DatePicker;
+using ATimePicker = Android.Widget.TimePicker;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class PickerRenderer : ViewRenderer<Picker, EditText>
+ {
+ AlertDialog _dialog;
+
+ bool _isDisposed;
+
+ public PickerRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_isDisposed)
+ {
+ _isDisposed = true;
+ ((ObservableList<string>)Element.Items).CollectionChanged -= RowsCollectionChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
+ {
+ if (e.OldElement != null)
+ ((ObservableList<string>)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
+
+ if (e.NewElement != null)
+ {
+ ((ObservableList<string>)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
+ if (Control == null)
+ {
+ var textField = new EditText(Context) { Focusable = false, Clickable = true, Tag = this };
+ textField.SetOnClickListener(PickerListener.Instance);
+ SetNativeControl(textField);
+ }
+ UpdatePicker();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Picker.TitleProperty.PropertyName)
+ UpdatePicker();
+ if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName)
+ UpdatePicker();
+ }
+
+ internal override void OnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs e)
+ {
+ base.OnFocusChangeRequested(sender, e);
+
+ if (e.Focus)
+ OnClick();
+ else if (_dialog != null)
+ {
+ _dialog.Hide();
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ Control.ClearFocus();
+ _dialog = null;
+ }
+ }
+
+ void OnClick()
+ {
+ Picker model = Element;
+
+ var picker = new NumberPicker(Context);
+ if (model.Items != null && model.Items.Any())
+ {
+ picker.MaxValue = model.Items.Count - 1;
+ picker.MinValue = 0;
+ picker.SetDisplayedValues(model.Items.ToArray());
+ picker.WrapSelectorWheel = false;
+ picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
+ picker.Value = model.SelectedIndex;
+ }
+
+ var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
+ layout.AddView(picker);
+
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+
+ var builder = new AlertDialog.Builder(Context);
+ builder.SetView(layout);
+ builder.SetTitle(model.Title ?? "");
+ builder.SetNegativeButton(global::Android.Resource.String.Cancel, (s, a) =>
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ // It is possible for the Content of the Page to be changed when Focus is changed.
+ // In this case, we'll lose our Control.
+ Control?.ClearFocus();
+ _dialog = null;
+ });
+ builder.SetPositiveButton(global::Android.Resource.String.Ok, (s, a) =>
+ {
+ ((IElementController)Element).SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
+ // It is possible for the Content of the Page to be changed on SelectedIndexChanged.
+ // In this case, the Element & Control will no longer exist.
+ if (Element != null)
+ {
+ if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
+ Control.Text = model.Items[Element.SelectedIndex];
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ // It is also possible for the Content of the Page to be changed when Focus is changed.
+ // In this case, we'll lose our Control.
+ Control?.ClearFocus();
+ }
+ _dialog = null;
+ });
+
+ (_dialog = builder.Create()).Show();
+ }
+
+ void RowsCollectionChanged(object sender, EventArgs e)
+ {
+ UpdatePicker();
+ }
+
+ void UpdatePicker()
+ {
+ Control.Hint = Element.Title;
+
+ string oldText = Control.Text;
+
+ if (Element.SelectedIndex == -1 || Element.Items == null)
+ Control.Text = null;
+ else
+ Control.Text = Element.Items[Element.SelectedIndex];
+
+ if (oldText != Control.Text)
+ ((IVisualElementController)Element).NativeSizeChanged();
+ }
+
+ class PickerListener : Object, IOnClickListener
+ {
+ public static readonly PickerListener Instance = new PickerListener();
+
+ public void OnClick(global::Android.Views.View v)
+ {
+ var renderer = v.Tag as PickerRenderer;
+ if (renderer == null)
+ return;
+
+ renderer.OnClick();
+ }
+ }
+ }
+} \ No newline at end of file