-
Notifications
You must be signed in to change notification settings - Fork 1.9k
TimePicker Handlers #454
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
TimePicker Handlers #454
Changes from 6 commits
2708928
14137d7
15e1373
0cb12df
9fe3d26
a9b200f
c8660b1
80f034a
f2ea57a
76bb2dd
a12e859
fd88755
5341654
f85e18a
4806c25
ae273ca
627610f
2531455
eb36ce9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| namespace Microsoft.Maui.Controls | ||
| { | ||
| public partial class TimePicker : ITimePicker | ||
| { | ||
|
|
||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| using System; | ||
|
|
||
| namespace Microsoft.Maui | ||
| { | ||
| public interface ITimePicker : IView | ||
| { | ||
| string Format { get; } | ||
| TimeSpan Time { get; set; } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| using System; | ||
| using Android.App; | ||
|
|
||
| namespace Microsoft.Maui.Handlers | ||
| { | ||
| public partial class TimePickerHandler : AbstractViewHandler<ITimePicker, MauiTimePicker> | ||
| { | ||
| MauiTimePicker? _timePicker; | ||
| AlertDialog? _dialog; | ||
|
|
||
| protected override MauiTimePicker CreateNativeView() | ||
| { | ||
| _timePicker = new MauiTimePicker(Context) | ||
| { | ||
| ShowPicker = ShowPickerDialog, | ||
| HidePicker = HidePickerDialog | ||
| }; | ||
|
|
||
| return _timePicker; | ||
| } | ||
|
|
||
| protected override void DisconnectHandler(MauiTimePicker nativeView) | ||
| { | ||
| if (_dialog != null) | ||
| { | ||
| _dialog.Hide(); | ||
| _dialog = null; | ||
| } | ||
| } | ||
|
|
||
| protected virtual TimePickerDialog CreateTimePickerDialog(int hour, int minute) | ||
| { | ||
| void onTimeSetCallback(object? obj, TimePickerDialog.TimeSetEventArgs args) | ||
| { | ||
| if (VirtualView == null || TypedNativeView == null) | ||
| return; | ||
|
|
||
| VirtualView.Time = new TimeSpan(args.HourOfDay, args.Minute, 0); | ||
| } | ||
|
|
||
| var dialog = new TimePickerDialog(Context!, onTimeSetCallback, hour, minute, _timePicker != null && _timePicker.Is24HourView(VirtualView)); | ||
|
|
||
| return dialog; | ||
| } | ||
|
|
||
| public static void MapFormat(TimePickerHandler handler, ITimePicker timePicker) | ||
| { | ||
| handler.TypedNativeView?.UpdateFormat(timePicker); | ||
| } | ||
|
|
||
| public static void MapTime(TimePickerHandler handler, ITimePicker timePicker) | ||
| { | ||
| handler.TypedNativeView?.UpdateTime(timePicker); | ||
| } | ||
|
|
||
| void ShowPickerDialog() | ||
| { | ||
| if (VirtualView == null) | ||
| return; | ||
|
|
||
| var time = VirtualView.Time; | ||
| ShowPickerDialog(time.Hours, time.Minutes); | ||
| } | ||
|
|
||
| // This overload is here so we can pass in the current values from the dialog | ||
| // on an orientation change (so that orientation changes don't cause the user's date selection progress | ||
| // to be lost). Not useful until we have orientation changed events. | ||
| void ShowPickerDialog(int hour, int minute) | ||
| { | ||
| _dialog = CreateTimePickerDialog(hour, minute); | ||
| _dialog.Show(); | ||
| } | ||
|
|
||
| void HidePickerDialog() | ||
| { | ||
| _dialog?.Hide(); | ||
hartez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| using System; | ||
|
|
||
| namespace Microsoft.Maui.Handlers | ||
| { | ||
| public partial class TimePickerHandler : AbstractViewHandler<ITimePicker, object> | ||
| { | ||
| protected override object CreateNativeView() => throw new NotImplementedException(); | ||
|
|
||
| public static void MapFormat(TimePickerHandler handler, ITimePicker view) { } | ||
| public static void MapTime(TimePickerHandler handler, ITimePicker view) { } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| namespace Microsoft.Maui.Handlers | ||
| { | ||
| public partial class TimePickerHandler | ||
| { | ||
| public static PropertyMapper<ITimePicker, TimePickerHandler> TimePickerMapper = new PropertyMapper<ITimePicker, TimePickerHandler>(ViewHandler.ViewMapper) | ||
| { | ||
| [nameof(ITimePicker.Format)] = MapFormat, | ||
| [nameof(ITimePicker.Time)] = MapTime | ||
| }; | ||
|
|
||
| public TimePickerHandler() : base(TimePickerMapper) | ||
| { | ||
|
|
||
| } | ||
|
|
||
| public TimePickerHandler(PropertyMapper mapper) : base(mapper ?? TimePickerMapper) | ||
| { | ||
|
|
||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| using System; | ||
| using Foundation; | ||
| using UIKit; | ||
| using RectangleF = CoreGraphics.CGRect; | ||
|
|
||
| namespace Microsoft.Maui.Handlers | ||
| { | ||
| public partial class TimePickerHandler : AbstractViewHandler<ITimePicker, MauiTimePicker> | ||
| { | ||
| MauiTimePicker? _nativeTimePicker; | ||
| static UIDatePicker? Picker; | ||
mattleibow marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| protected override MauiTimePicker CreateNativeView() | ||
| { | ||
| _nativeTimePicker = new MauiTimePicker(); | ||
|
|
||
| Picker = new UIDatePicker { Mode = UIDatePickerMode.Time, TimeZone = new NSTimeZone("UTC") }; | ||
|
|
||
| if (NativeVersion.IsAtLeast(14)) | ||
| { | ||
| Picker.PreferredDatePickerStyle = UIDatePickerStyle.Wheels; | ||
| } | ||
|
|
||
| var width = UIScreen.MainScreen.Bounds.Width; | ||
| var toolbar = new UIToolbar(new RectangleF(0, 0, width, 44)) { BarStyle = UIBarStyle.Default, Translucent = true }; | ||
| var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace); | ||
|
|
||
| var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, a) => | ||
| { | ||
| SetVirtualViewTime(); | ||
| _nativeTimePicker.ResignFirstResponder(); | ||
| }); | ||
|
|
||
| toolbar.SetItems(new[] { spacer, doneButton }, false); | ||
|
|
||
| _nativeTimePicker.InputView = Picker; | ||
| _nativeTimePicker.InputAccessoryView = toolbar; | ||
|
|
||
| _nativeTimePicker.InputView.AutoresizingMask = UIViewAutoresizing.FlexibleHeight; | ||
| _nativeTimePicker.InputAccessoryView.AutoresizingMask = UIViewAutoresizing.FlexibleHeight; | ||
|
|
||
| _nativeTimePicker.InputAssistantItem.LeadingBarButtonGroups = null; | ||
| _nativeTimePicker.InputAssistantItem.TrailingBarButtonGroups = null; | ||
|
|
||
| _nativeTimePicker.AccessibilityTraits = UIAccessibilityTrait.Button; | ||
|
|
||
| return _nativeTimePicker; | ||
| } | ||
|
|
||
| protected override void ConnectHandler(MauiTimePicker nativeView) | ||
| { | ||
| if (Picker != null) | ||
| Picker.ValueChanged += OnValueChanged; | ||
| } | ||
|
|
||
| protected override void DisconnectHandler(MauiTimePicker nativeView) | ||
| { | ||
| if (Picker != null) | ||
| { | ||
| Picker.RemoveFromSuperview(); | ||
| Picker.ValueChanged -= OnValueChanged; | ||
| Picker.Dispose(); | ||
| Picker = null; | ||
| } | ||
| } | ||
|
|
||
| public static void MapFormat(TimePickerHandler handler, ITimePicker timePicker) | ||
| { | ||
| handler.TypedNativeView?.UpdateFormat(timePicker, Picker); | ||
mattleibow marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| public static void MapTime(TimePickerHandler handler, ITimePicker timePicker) | ||
| { | ||
| handler.TypedNativeView?.UpdateTime(timePicker, Picker); | ||
| } | ||
|
|
||
| void OnValueChanged(object? sender, EventArgs e) | ||
| { | ||
| SetVirtualViewTime(); | ||
| } | ||
|
|
||
| void SetVirtualViewTime() | ||
| { | ||
| if (VirtualView == null || Picker == null) | ||
| return; | ||
|
|
||
| VirtualView.Time = Picker.Date.ToDateTime() - new DateTime(1, 1, 1); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| using System; | ||
| using Android.Content; | ||
| using Android.Runtime; | ||
| using Android.Util; | ||
| using Android.Views; | ||
| using Android.Widget; | ||
| using static Android.Views.View; | ||
|
|
||
| namespace Microsoft.Maui | ||
| { | ||
| public class MauiTimePicker : EditText, IOnClickListener | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there some overlap with the Picker? I see some derived types here: https://github.com/dotnet/maui/pull/433/files#diff-df34a6df84bad7762b1ed8a016db8d80eeb0e1c94f25562446e52424f94a196a Also, there is a PickerManager that might have some things that we may want/need? https://github.com/dotnet/maui/pull/433/files#diff-ba5788b29220792f8b9f67a65077c6b25781a9cfd8b59ef06896671af9b24efe Should these both be using a shared base type that is a PickerEditText and then each type of picker just ahs a thin wrapper for it? |
||
| { | ||
| public MauiTimePicker(Context? context) : base(context) | ||
| { | ||
| Initialize(); | ||
| } | ||
|
|
||
| public MauiTimePicker(Context? context, IAttributeSet attrs) : base(context, attrs) | ||
| { | ||
| Initialize(); | ||
| } | ||
|
|
||
| public MauiTimePicker(Context? context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr) | ||
| { | ||
| Initialize(); | ||
| } | ||
|
|
||
| protected MauiTimePicker(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) | ||
| { | ||
| } | ||
|
|
||
| private void Initialize() | ||
| { | ||
| Focusable = true; | ||
| SetOnClickListener(this); | ||
| } | ||
|
|
||
| public Action? ShowPicker { get; set; } | ||
| public Action? HidePicker { get; set; } | ||
|
|
||
| public void OnClick(View? v) | ||
| { | ||
| ShowPicker?.Invoke(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| using System; | ||
| using Android.Text.Format; | ||
|
|
||
| namespace Microsoft.Maui | ||
| { | ||
| public static class TimePickerExtensions | ||
| { | ||
| public static void UpdateFormat(this MauiTimePicker mauiTimePicker, ITimePicker view) | ||
| { | ||
| mauiTimePicker.SetTime(view); | ||
| } | ||
|
|
||
| public static void UpdateTime(this MauiTimePicker mauiTimePicker, ITimePicker view) | ||
| { | ||
| mauiTimePicker.SetTime(view); | ||
| } | ||
|
|
||
| internal static bool Is24HourView(this MauiTimePicker mauiTimePicker, ITimePicker? timePicker) | ||
| { | ||
| return timePicker != null && (DateFormat.Is24HourFormat(mauiTimePicker.Context) && timePicker.Format == "t" || timePicker.Format == "HH:mm"); | ||
| } | ||
|
|
||
| internal static void SetTime(this MauiTimePicker mauiTimePicker, ITimePicker timePicker) | ||
| { | ||
| var time = timePicker.Time; | ||
|
|
||
| if (string.IsNullOrEmpty(timePicker.Format)) | ||
| { | ||
| var timeFormat = "t"; | ||
| mauiTimePicker.Text = DateTime.Today.Add(time).ToString(timeFormat); | ||
| } | ||
| else | ||
| { | ||
| var timeFormat = timePicker.Format; | ||
| mauiTimePicker.Text = DateTime.Today.Add(time).ToString(timeFormat); | ||
| } | ||
| } | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.