From 5fd60db46758bb961a579bab69b330f6b25ecaff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=8A=B9=EA=B7=BC/Common=20Platform=20Lab=28SR?= =?UTF-8?q?=29/=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Tue, 3 May 2022 09:51:36 +0900 Subject: [PATCH] Update for focus navigation (#459) --- .../AlertManager/AlertManager.Tizen.cs | 117 +++++++++++------- .../Tizen/Extensions/ToolbarExtensions.cs | 24 ++-- .../Handlers/Picker/PickerHandler.Tizen.cs | 34 +++-- .../SearchBar/SearchBarHandler.Tizen.cs | 6 +- .../TimePicker/TimePickerHandler.Tizen.cs | 34 +++-- .../src/Platform/Tizen/MauiApplication.cs | 2 +- src/Core/src/Platform/Tizen/MauiSearchBar.cs | 14 ++- .../Tizen/NavigationStackExtensions.cs | 37 ++++++ .../src/Platform/Tizen/WindowExtensions.cs | 6 +- 9 files changed, 192 insertions(+), 82 deletions(-) create mode 100644 src/Core/src/Platform/Tizen/NavigationStackExtensions.cs diff --git a/src/Controls/src/Core/Platform/AlertManager/AlertManager.Tizen.cs b/src/Controls/src/Core/Platform/AlertManager/AlertManager.Tizen.cs index 0699af314306..9591a344cea6 100644 --- a/src/Controls/src/Core/Platform/AlertManager/AlertManager.Tizen.cs +++ b/src/Controls/src/Core/Platform/AlertManager/AlertManager.Tizen.cs @@ -16,11 +16,11 @@ internal partial class AlertManager internal void Subscribe(Window window) { var nativeWindow = window?.MauiContext.GetPlatformWindow(); - + var modalStack = window?.MauiContext.GetModalStack(); if (Subscriptions.Any(s => s.Window == nativeWindow)) return; - Subscriptions.Add(new AlertRequestHelper(nativeWindow)); + Subscriptions.Add(new AlertRequestHelper(nativeWindow, modalStack)); } internal void Unsubscribe(Window window) @@ -42,7 +42,9 @@ internal sealed class AlertRequestHelper : IDisposable int _busyCount; Popup _busyPopup; - internal AlertRequestHelper(NWindow window) + NavigationStack _modalStack; + + internal AlertRequestHelper(NWindow window, NavigationStack modalStack) { Window = window; @@ -50,6 +52,7 @@ internal AlertRequestHelper(NWindow window) MessagingCenter.Subscribe(Window, Page.AlertSignalName, OnAlertRequest); MessagingCenter.Subscribe(Window, Page.ActionSheetSignalName, OnActionSheetRequest); MessagingCenter.Subscribe(Window, Page.PromptSignalName, OnPromptRequested); + _modalStack = modalStack; } public NWindow Window { get; } @@ -73,25 +76,10 @@ void OnBusySetRequest(Page sender, bool enabled) if (null == _busyPopup) { - _busyPopup = new Popup - { - BackgroundColor = new Tizen.NUI.Color(0.1f, 0.1f, 0.1f, 0.5f), - Layout = new LinearLayout - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - }, - Content = new Tizen.UIExtensions.NUI.GraphicsView.ActivityIndicator - { - // TODO. need to fix - SizeWidth = 100, - SizeHeight = 100, - IsRunning = true, - } - }; + _busyPopup = new BusyPopup(); } - if (_busyCount > 0) + if (_busyCount > 0 && !_busyPopup.IsOpen) { _busyPopup.Open(); } @@ -118,14 +106,19 @@ async void OnAlertRequest(Page sender, AlertArguments arguments) { alert = new MessagePopup(arguments.Title, arguments.Message, arguments.Cancel); } - try - { - arguments.SetResult(await alert.Open()); - } - catch (TaskCanceledException) - { - arguments.SetResult(false); - } + + await _modalStack.PushDummyPopupPage(async () => { + try + { + arguments.SetResult(await alert.Open()); + } + catch (TaskCanceledException) + { + arguments.SetResult(false); + } + }); + + alert?.Dispose(); } async void OnActionSheetRequest(Page sender, ActionSheetArguments arguments) @@ -134,15 +127,17 @@ async void OnActionSheetRequest(Page sender, ActionSheetArguments arguments) if (!PageIsInThisWindow(sender)) return; - try - { - var popup = new ActionSheetPopup(arguments.Title, arguments.Cancel, destruction: arguments.Destruction, buttons: arguments.Buttons); - arguments.SetResult(await popup.Open()); - } - catch (TaskCanceledException) - { - arguments.SetResult(arguments.Cancel); - } + await _modalStack.PushDummyPopupPage(async () => { + try + { + using var popup = new ActionSheetPopup(arguments.Title, arguments.Cancel, destruction: arguments.Destruction, buttons: arguments.Buttons); + arguments.SetResult(await popup.Open()); + } + catch (TaskCanceledException) + { + arguments.SetResult(arguments.Cancel); + } + }); } async void OnPromptRequested(Page sender, PromptArguments args) @@ -151,16 +146,19 @@ async void OnPromptRequested(Page sender, PromptArguments args) if (!PageIsInThisWindow(sender)) return; - try - { - // placeholder should not be empty string, if not layout is broken - var popup = new PromptPopup(args.Title, args.Message, args.Accept, args.Cancel, args.Placeholder ?? " ", args.MaxLength, args.Keyboard.ToPlatform(), args.InitialValue); - args.SetResult(await popup.Open()); - } - catch (TaskCanceledException) - { - args.SetResult(null); - } + + await _modalStack.PushDummyPopupPage(async () => { + try + { + // placeholder should not be empty string, if not layout is broken + using var popup = new PromptPopup(args.Title, args.Message, args.Accept, args.Cancel, args.Placeholder ?? " ", args.MaxLength, args.Keyboard.ToPlatform(), args.InitialValue); + args.SetResult(await popup.Open()); + } + catch (TaskCanceledException) + { + args.SetResult(null); + } + }); } bool PageIsInThisWindow(IView sender) @@ -168,5 +166,30 @@ bool PageIsInThisWindow(IView sender) var window = sender.Handler?.MauiContext?.GetPlatformWindow() ?? null; return window == Window; } + + class BusyPopup : Popup + { + public BusyPopup() + { + BackgroundColor = new Color(0.1f, 0.1f, 0.1f, 0.5f); + Layout = new LinearLayout + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + }; + Content = new Tizen.UIExtensions.NUI.GraphicsView.ActivityIndicator + { + + SizeWidth = 100, + SizeHeight = 100, + IsRunning = true, + }; + } + + protected override bool OnBackButtonPressed() + { + return true; + } + } } } diff --git a/src/Controls/src/Core/Platform/Tizen/Extensions/ToolbarExtensions.cs b/src/Controls/src/Core/Platform/Tizen/Extensions/ToolbarExtensions.cs index 815671758c3a..78058f238825 100644 --- a/src/Controls/src/Core/Platform/Tizen/Extensions/ToolbarExtensions.cs +++ b/src/Controls/src/Core/Platform/Tizen/Extensions/ToolbarExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Microsoft.Maui.Graphics; using Tizen.NUI.BaseComponents; using Tizen.UIExtensions.NUI; @@ -110,17 +111,22 @@ public static void UpdateMenuItems(this MauiToolbar platformToolbar, Toolbar too { var actions = secondaryActions.ToList(); var actionTexts = actions.Select(i => i.Text).ToList(); - using (var popup = new ActionSheetPopup("", "Cancel", null, buttons: actionTexts)) + var modalStack = toolbar?.Handler.MauiContext?.GetModalStack(); + if (modalStack != null) { - try + await modalStack.PushDummyPopupPage(async () => { - var select = actionTexts.IndexOf(await popup.Open()); - actions[select].Command.Execute(actions[select].CommandParameter); - } - catch - { - // Cancel - } + try + { + using var popup = new ActionSheetPopup("", "Cancel", null, buttons: actionTexts); + var select = actionTexts.IndexOf(await popup.Open()); + actions[select].Command.Execute(actions[select].CommandParameter); + } + catch + { + // Cancel + } + }); } }; platformToolbar.Actions.Add(more); diff --git a/src/Core/src/Handlers/Picker/PickerHandler.Tizen.cs b/src/Core/src/Handlers/Picker/PickerHandler.Tizen.cs index 1a429b8a8a31..ebb7b66fd82e 100644 --- a/src/Core/src/Handlers/Picker/PickerHandler.Tizen.cs +++ b/src/Core/src/Handlers/Picker/PickerHandler.Tizen.cs @@ -14,12 +14,14 @@ public partial class PickerHandler : ViewHandler protected override void ConnectHandler(NEntry platformView) { platformView.TouchEvent += OnTouch; + platformView.KeyEvent += OnKeyEvent; base.ConnectHandler(platformView); } protected override void DisconnectHandler(NEntry platformView) { platformView.TouchEvent -= OnTouch; + platformView.KeyEvent -= OnKeyEvent; base.DisconnectHandler(platformView); } @@ -87,21 +89,37 @@ bool OnTouch(object source, Tizen.NUI.BaseComponents.View.TouchEventArgs e) return true; } + bool OnKeyEvent(object source, Tizen.NUI.BaseComponents.View.KeyEventArgs e) + { + if (e.Key.State == Tizen.NUI.Key.StateType.Up && (e.Key.KeyPressedName == "Return" || e.Key.KeyPressedName == "Enter")) + { + OpenPopupAsync(); + return true; + } + return false; + } + + async void OpenPopupAsync() { if (VirtualView == null) return; - using (var popup = new ActionSheetPopup(VirtualView.Title, "Cancel", null, VirtualView.GetItemsAsArray())) + var modalStack = MauiContext?.GetModalStack(); + if (modalStack != null) { - try - { - VirtualView.SelectedIndex = VirtualView.GetItemsAsArray().IndexOf(await popup.Open()); - } - catch + await modalStack.PushDummyPopupPage(async () => { - // Cancel - } + try + { + using var popup = new ActionSheetPopup(VirtualView.Title, "Cancel", null, VirtualView.GetItemsAsArray()); + VirtualView.SelectedIndex = VirtualView.GetItemsAsArray().IndexOf(await popup.Open()); + } + catch + { + // Cancel + } + }); } } diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler.Tizen.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler.Tizen.cs index db125d7182ab..daafc5b0964c 100644 --- a/src/Core/src/Handlers/SearchBar/SearchBarHandler.Tizen.cs +++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler.Tizen.cs @@ -4,11 +4,7 @@ namespace Microsoft.Maui.Handlers { public partial class SearchBarHandler : ViewHandler { - protected override MauiSearchBar CreatePlatformView() => new() - { - Focusable = true, - FocusableInTouch = true, - }; + protected override MauiSearchBar CreatePlatformView() => new(); protected override void ConnectHandler(MauiSearchBar platformView) { diff --git a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Tizen.cs b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Tizen.cs index c3f76c25b7a2..49da27708cff 100644 --- a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Tizen.cs +++ b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Tizen.cs @@ -1,4 +1,5 @@ using Tizen.NUI; +using Tizen.UIExtensions.NUI; using NEntry = Tizen.UIExtensions.NUI.Entry; namespace Microsoft.Maui.Handlers @@ -15,12 +16,14 @@ public partial class TimePickerHandler : ViewHandler protected override void ConnectHandler(NEntry platformView) { platformView.TouchEvent += OnTouch; + platformView.KeyEvent += OnKeyEvent; base.ConnectHandler(platformView); } protected override void DisconnectHandler(NEntry platformView) { platformView.TouchEvent -= OnTouch; + platformView.KeyEvent -= OnKeyEvent; base.DisconnectHandler(platformView); } @@ -60,21 +63,36 @@ bool OnTouch(object source, Tizen.NUI.BaseComponents.View.TouchEventArgs e) return true; } + bool OnKeyEvent(object source, Tizen.NUI.BaseComponents.View.KeyEventArgs e) + { + if (e.Key.IsAcceptKeyEvent()) + { + OpenPopupAsync(); + return true; + } + return false; + } + async void OpenPopupAsync() { if (VirtualView == null) return; - using (var popup = new MauiTimePicker(VirtualView.Time)) + var modalStack = MauiContext?.GetModalStack(); + if (modalStack != null) { - try - { - VirtualView.Time = await popup.Open(); - } - catch + await modalStack.PushDummyPopupPage(async () => { - // Cancel - } + try + { + using var popup = new MauiTimePicker(VirtualView.Time); + VirtualView.Time = await popup.Open(); + } + catch + { + // Cancel + } + }); } } diff --git a/src/Core/src/Platform/Tizen/MauiApplication.cs b/src/Core/src/Platform/Tizen/MauiApplication.cs index cb117e714ac0..0d259f468185 100644 --- a/src/Core/src/Platform/Tizen/MauiApplication.cs +++ b/src/Core/src/Platform/Tizen/MauiApplication.cs @@ -24,9 +24,9 @@ protected MauiApplication() protected override void OnPreCreate() { base.OnPreCreate(); + FocusManager.Instance.EnableDefaultAlgorithm(true); var mauiApp = CreateMauiApp(); - var rootContext = new MauiContext(mauiApp.Services); var platformWindow = CoreAppExtensions.GetDefaultWindow(); diff --git a/src/Core/src/Platform/Tizen/MauiSearchBar.cs b/src/Core/src/Platform/Tizen/MauiSearchBar.cs index 67a0db40fb76..4dbb2090cf0d 100644 --- a/src/Core/src/Platform/Tizen/MauiSearchBar.cs +++ b/src/Core/src/Platform/Tizen/MauiSearchBar.cs @@ -31,9 +31,11 @@ public MauiSearchBar() _entry.KeyEvent += OnKeyEvent; _searchButton = new TSkiaGraphicsView { + Focusable = true, Drawable = new SearchIcon(), }; _searchButton.TouchEvent += OnSearchButtonTouchEvent; + _searchButton.KeyEvent += OnSearchButtonKeyEvent; Children.Add(_entry); Children.Add(_searchButton); @@ -69,7 +71,7 @@ void OnSearchButtonClicked(object? sender, EventArgs e) bool OnKeyEvent(object source, KeyEventArgs e) { - if (e.Key.State == Key.StateType.Down && e.Key.KeyPressedName == "Return") + if (e.Key.IsAcceptKeyEvent()) { SearchButtonPressed?.Invoke(this, EventArgs.Empty); return true; @@ -90,6 +92,16 @@ bool OnSearchButtonTouchEvent(object source, TouchEventArgs e) return state == PointStateType.Up || state == PointStateType.Down; } + bool OnSearchButtonKeyEvent(object source, KeyEventArgs e) + { + if (e.Key.IsAcceptKeyEvent()) + { + SearchButtonPressed?.Invoke(this, EventArgs.Empty); + return true; + } + return false; + } + void OnLayoutUpdated(object? sender, LayoutEventArgs e) { var margin = (float)IconMargin.ToScaledPixel(); diff --git a/src/Core/src/Platform/Tizen/NavigationStackExtensions.cs b/src/Core/src/Platform/Tizen/NavigationStackExtensions.cs new file mode 100644 index 000000000000..f37509439cec --- /dev/null +++ b/src/Core/src/Platform/Tizen/NavigationStackExtensions.cs @@ -0,0 +1,37 @@ +using System; +using System.Threading.Tasks; +using Tizen.UIExtensions.NUI; +using NView = Tizen.NUI.BaseComponents.View; + +namespace Microsoft.Maui.Platform +{ + public static class NavigationStackExtensions + { + public static async Task PushDummyPopupPage(this NavigationStack stack, Func openPopup) + { + var dummy = new NView(); + stack.ShownBehindPage = true; + _ = stack.Push(dummy, false); + stack.ShownBehindPage = false; + try + { + await openPopup(); + } + catch + { + // ignore all exceptions + } + finally + { + if (stack.Top == dummy) + { + _ = stack.Pop(false); + } + else + { + stack.Pop(dummy); + } + } + } + } +} \ No newline at end of file diff --git a/src/Core/src/Platform/Tizen/WindowExtensions.cs b/src/Core/src/Platform/Tizen/WindowExtensions.cs index a44c7b3ec176..17d2b406a0a8 100644 --- a/src/Core/src/Platform/Tizen/WindowExtensions.cs +++ b/src/Core/src/Platform/Tizen/WindowExtensions.cs @@ -38,12 +38,12 @@ public static void Initialize(this Window platformWindow) platformWindow.KeyEvent += (s, e) => { - if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape")) + if (e.Key.IsDeclineKeyEvent()) { if (Popup.HasOpenedPopup) { - Popup.CloseLast(); - return; + if (Popup.CloseLast()) + return; } OnBackButtonPressed(platformWindow); }