Skip to content

Commit 4329dcf

Browse files
github-actions[bot]CopilotPureWeen
authored
[release/10.0.1xx-rc1] Expose Android Activity and Modal Dialog OnKey* overrides via ConfigureLifecycleEvents with generalized context parameter (#31237)
* Initial plan * Add OnKey* lifecycle events for Android Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com> * Add comprehensive tests and demo for OnKey* lifecycle events Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com> * Add OnKey* lifecycle events to modal dialog CustomComponentDialog Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com> * Revert sandbox project changes as requested Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com> * Fix KeyEvent nullability and generalize OnKey* lifecycle event implementation Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com> * - fix publicapi * Revert changes to LifecycleEventsTests.cs as requested Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com> Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
1 parent 68bc8d4 commit 4329dcf

File tree

6 files changed

+367
-0
lines changed

6 files changed

+367
-0
lines changed

src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Android.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,61 @@ public CustomComponentDialog(Context context, int themeResId) : base(context, th
398398
this.OnBackPressedDispatcher.AddCallback(new CallBack(true, this));
399399
}
400400

401+
public override bool OnKeyDown(Keycode keyCode, KeyEvent e)
402+
{
403+
var handled = false;
404+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyDown>(del =>
405+
{
406+
handled = del(this, keyCode, e) || handled;
407+
});
408+
409+
return handled || base.OnKeyDown(keyCode, e);
410+
}
411+
412+
public override bool OnKeyLongPress(Keycode keyCode, KeyEvent e)
413+
{
414+
var handled = false;
415+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyLongPress>(del =>
416+
{
417+
handled = del(this, keyCode, e) || handled;
418+
});
419+
420+
return handled || base.OnKeyLongPress(keyCode, e);
421+
}
422+
423+
public override bool OnKeyMultiple(Keycode keyCode, int repeatCount, KeyEvent e)
424+
{
425+
var handled = false;
426+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyMultiple>(del =>
427+
{
428+
handled = del(this, keyCode, repeatCount, e) || handled;
429+
});
430+
431+
return handled || base.OnKeyMultiple(keyCode, repeatCount, e);
432+
}
433+
434+
public override bool OnKeyShortcut(Keycode keyCode, KeyEvent e)
435+
{
436+
var handled = false;
437+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyShortcut>(del =>
438+
{
439+
handled = del(this, keyCode, e) || handled;
440+
});
441+
442+
return handled || base.OnKeyShortcut(keyCode, e);
443+
}
444+
445+
public override bool OnKeyUp(Keycode keyCode, KeyEvent e)
446+
{
447+
var handled = false;
448+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyUp>(del =>
449+
{
450+
handled = del(this, keyCode, e) || handled;
451+
});
452+
453+
return handled || base.OnKeyUp(keyCode, e);
454+
}
455+
401456
sealed class CallBack : OnBackPressedCallback
402457
{
403458
WeakReference<CustomComponentDialog> _customComponentDialog;

src/Core/src/LifecycleEvents/Android/AndroidLifecycle.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Android.Content.PM;
44
using Android.Content.Res;
55
using Android.OS;
6+
using Android.Views;
67

78
namespace Microsoft.Maui.LifecycleEvents
89
{
@@ -33,6 +34,11 @@ public static class AndroidLifecycle
3334
public delegate void OnActivityResult(Activity activity, int requestCode, Result resultCode, Intent? data);
3435
public delegate bool OnBackPressed(Activity activity);
3536
public delegate void OnConfigurationChanged(Activity activity, Configuration newConfig);
37+
public delegate bool OnKeyDown(object context, Keycode keyCode, KeyEvent? e);
38+
public delegate bool OnKeyLongPress(object context, Keycode keyCode, KeyEvent? e);
39+
public delegate bool OnKeyMultiple(object context, Keycode keyCode, int repeatCount, KeyEvent? e);
40+
public delegate bool OnKeyShortcut(object context, Keycode keyCode, KeyEvent? e);
41+
public delegate bool OnKeyUp(object context, Keycode keyCode, KeyEvent? e);
3642
public delegate void OnNewIntent(Activity activity, Intent? intent);
3743
public delegate void OnRequestPermissionsResult(Activity activity, int requestCode, string[] permissions, Permission[] grantResults);
3844
public delegate void OnRestoreInstanceState(Activity activity, Bundle savedInstanceState);

src/Core/src/LifecycleEvents/Android/AndroidLifecycleBuilderExtensions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ public static class AndroidLifecycleBuilderExtensions
1313
public static IAndroidLifecycleBuilder OnConfigurationChanged(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnConfigurationChanged del) => lifecycle.OnEvent(del);
1414
public static IAndroidLifecycleBuilder OnCreate(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnCreate del) => lifecycle.OnEvent(del);
1515
public static IAndroidLifecycleBuilder OnDestroy(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnDestroy del) => lifecycle.OnEvent(del);
16+
public static IAndroidLifecycleBuilder OnKeyDown(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnKeyDown del) => lifecycle.OnEvent(del);
17+
public static IAndroidLifecycleBuilder OnKeyLongPress(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnKeyLongPress del) => lifecycle.OnEvent(del);
18+
public static IAndroidLifecycleBuilder OnKeyMultiple(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnKeyMultiple del) => lifecycle.OnEvent(del);
19+
public static IAndroidLifecycleBuilder OnKeyShortcut(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnKeyShortcut del) => lifecycle.OnEvent(del);
20+
public static IAndroidLifecycleBuilder OnKeyUp(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnKeyUp del) => lifecycle.OnEvent(del);
1621
public static IAndroidLifecycleBuilder OnNewIntent(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnNewIntent del) => lifecycle.OnEvent(del);
1722
public static IAndroidLifecycleBuilder OnPause(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnPause del) => lifecycle.OnEvent(del);
1823
public static IAndroidLifecycleBuilder OnPostCreate(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnPostCreate del) => lifecycle.OnEvent(del);

src/Core/src/Platform/Android/MauiAppCompatActivity.Lifecycle.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Android.Content.PM;
55
using Android.Content.Res;
66
using Android.OS;
7+
using Android.Views;
78
using Microsoft.Maui.Devices;
89
using Microsoft.Maui.LifecycleEvents;
910

@@ -89,5 +90,60 @@ protected override void OnRestoreInstanceState(Bundle savedInstanceState)
8990

9091
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnRestoreInstanceState>(del => del(this, savedInstanceState));
9192
}
93+
94+
public override bool OnKeyDown(Keycode keyCode, KeyEvent? e)
95+
{
96+
var handled = false;
97+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyDown>(del =>
98+
{
99+
handled = del(this, keyCode, e) || handled;
100+
});
101+
102+
return handled || base.OnKeyDown(keyCode, e);
103+
}
104+
105+
public override bool OnKeyLongPress(Keycode keyCode, KeyEvent? e)
106+
{
107+
var handled = false;
108+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyLongPress>(del =>
109+
{
110+
handled = del(this, keyCode, e) || handled;
111+
});
112+
113+
return handled || base.OnKeyLongPress(keyCode, e);
114+
}
115+
116+
public override bool OnKeyMultiple(Keycode keyCode, int repeatCount, KeyEvent? e)
117+
{
118+
var handled = false;
119+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyMultiple>(del =>
120+
{
121+
handled = del(this, keyCode, repeatCount, e) || handled;
122+
});
123+
124+
return handled || base.OnKeyMultiple(keyCode, repeatCount, e);
125+
}
126+
127+
public override bool OnKeyShortcut(Keycode keyCode, KeyEvent? e)
128+
{
129+
var handled = false;
130+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyShortcut>(del =>
131+
{
132+
handled = del(this, keyCode, e) || handled;
133+
});
134+
135+
return handled || base.OnKeyShortcut(keyCode, e);
136+
}
137+
138+
public override bool OnKeyUp(Keycode keyCode, KeyEvent? e)
139+
{
140+
var handled = false;
141+
IPlatformApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnKeyUp>(del =>
142+
{
143+
handled = del(this, keyCode, e) || handled;
144+
});
145+
146+
return handled || base.OnKeyUp(keyCode, e);
147+
}
92148
}
93149
}

src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ Microsoft.Maui.ITimePicker.IsOpen.set -> void
5353
Microsoft.Maui.ITimePicker.Time.get -> System.TimeSpan?
5454
Microsoft.Maui.IWebRequestInterceptingWebView
5555
Microsoft.Maui.IWebRequestInterceptingWebView.WebResourceRequested(Microsoft.Maui.WebResourceRequestedEventArgs! args) -> bool
56+
Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyDown
57+
Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyLongPress
58+
Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyMultiple
59+
Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyShortcut
60+
Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyUp
5661
Microsoft.Maui.Platform.MauiHorizontalScrollView
5762
Microsoft.Maui.Platform.MauiHorizontalScrollView.MauiHorizontalScrollView(Android.Content.Context? context, Android.Util.IAttributeSet? attrs) -> void
5863
Microsoft.Maui.Platform.MauiHorizontalScrollView.MauiHorizontalScrollView(Android.Content.Context? context, Android.Util.IAttributeSet? attrs, int defStyleAttr) -> void
@@ -191,6 +196,11 @@ override Microsoft.Maui.Handlers.OpenWindowRequest.GetHashCode() -> int
191196
override Microsoft.Maui.Handlers.OpenWindowRequest.ToString() -> string!
192197
override Microsoft.Maui.Handlers.RefreshViewHandler.SetVirtualView(Microsoft.Maui.IView! view) -> void
193198
override Microsoft.Maui.Handlers.TimePickerHandler.ConnectHandler(Microsoft.Maui.Platform.MauiTimePicker! platformView) -> void
199+
override Microsoft.Maui.MauiAppCompatActivity.OnKeyDown(Android.Views.Keycode keyCode, Android.Views.KeyEvent? e) -> bool
200+
override Microsoft.Maui.MauiAppCompatActivity.OnKeyLongPress(Android.Views.Keycode keyCode, Android.Views.KeyEvent? e) -> bool
201+
override Microsoft.Maui.MauiAppCompatActivity.OnKeyMultiple(Android.Views.Keycode keyCode, int repeatCount, Android.Views.KeyEvent? e) -> bool
202+
override Microsoft.Maui.MauiAppCompatActivity.OnKeyShortcut(Android.Views.Keycode keyCode, Android.Views.KeyEvent? e) -> bool
203+
override Microsoft.Maui.MauiAppCompatActivity.OnKeyUp(Android.Views.Keycode keyCode, Android.Views.KeyEvent? e) -> bool
194204
override Microsoft.Maui.Platform.MauiDatePicker.DefaultMovementMethod.get -> Android.Text.Method.IMovementMethod?
195205
override Microsoft.Maui.Platform.MauiHorizontalScrollView.Draw(Android.Graphics.Canvas? canvas) -> void
196206
override Microsoft.Maui.Platform.MauiHorizontalScrollView.HorizontalScrollBarEnabled.get -> bool
@@ -246,6 +256,11 @@ static Microsoft.Maui.Handlers.OpenWindowRequest.operator ==(Microsoft.Maui.Hand
246256
static Microsoft.Maui.Handlers.RefreshViewHandler.MapIsEnabled(Microsoft.Maui.Handlers.IRefreshViewHandler! handler, Microsoft.Maui.IRefreshView! refreshView) -> void
247257
static Microsoft.Maui.Handlers.SearchBarHandler.MapReturnType(Microsoft.Maui.Handlers.ISearchBarHandler! handler, Microsoft.Maui.ISearchBar! searchBar) -> void
248258
static Microsoft.Maui.Hosting.AppHostBuilderExtensions.ConfigureEnvironmentVariables(this Microsoft.Maui.Hosting.MauiAppBuilder! builder) -> Microsoft.Maui.Hosting.MauiAppBuilder!
259+
static Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions.OnKeyDown(this Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder! lifecycle, Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyDown! del) -> Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder!
260+
static Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions.OnKeyLongPress(this Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder! lifecycle, Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyLongPress! del) -> Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder!
261+
static Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions.OnKeyMultiple(this Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder! lifecycle, Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyMultiple! del) -> Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder!
262+
static Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions.OnKeyShortcut(this Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder! lifecycle, Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyShortcut! del) -> Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder!
263+
static Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions.OnKeyUp(this Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder! lifecycle, Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyUp! del) -> Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder!
249264
static Microsoft.Maui.Platform.ButtonExtensions.UpdateRippleColor(this Google.Android.Material.Button.MaterialButton! platformView, Microsoft.Maui.Graphics.Color? rippleColor) -> void
250265
static Microsoft.Maui.Platform.EditTextExtensions.GetCursorPosition(this Android.Widget.EditText! editText, int cursorOffset = 0) -> int
251266
static Microsoft.Maui.Platform.EditTextExtensions.GetSelectedTextLength(this Android.Widget.EditText! editText) -> int
@@ -309,6 +324,11 @@ virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnBackPressed.Invoke(And
309324
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnConfigurationChanged.Invoke(Android.App.Activity! activity, Android.Content.Res.Configuration! newConfig) -> void
310325
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnCreate.Invoke(Android.App.Activity! activity, Android.OS.Bundle? savedInstanceState) -> void
311326
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnDestroy.Invoke(Android.App.Activity! activity) -> void
327+
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyDown.Invoke(object! context, Android.Views.Keycode keyCode, Android.Views.KeyEvent? e) -> bool
328+
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyLongPress.Invoke(object! context, Android.Views.Keycode keyCode, Android.Views.KeyEvent? e) -> bool
329+
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyMultiple.Invoke(object! context, Android.Views.Keycode keyCode, int repeatCount, Android.Views.KeyEvent? e) -> bool
330+
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyShortcut.Invoke(object! context, Android.Views.Keycode keyCode, Android.Views.KeyEvent? e) -> bool
331+
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnKeyUp.Invoke(object! context, Android.Views.Keycode keyCode, Android.Views.KeyEvent? e) -> bool
312332
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnNewIntent.Invoke(Android.App.Activity! activity, Android.Content.Intent? intent) -> void
313333
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnPause.Invoke(Android.App.Activity! activity) -> void
314334
virtual Microsoft.Maui.LifecycleEvents.AndroidLifecycle.OnPostCreate.Invoke(Android.App.Activity! activity, Android.OS.Bundle? savedInstanceState) -> void

0 commit comments

Comments
 (0)