Skip to content

Commit e4f0c6e

Browse files
authored
[ContextMenu] Improvements to Android icon and auto-close when app goes to background (#324)
* made sure android does not crash if you add a icon to a context menu item * made sure we close the context menu when the app goes from background to foreground * made sure we close the context menu when the app goes to background on ios
1 parent 6b3c6ba commit e4f0c6e

File tree

3 files changed

+59
-7
lines changed

3 files changed

+59
-7
lines changed

src/DIPS.Xamarin.UI.Android/ContextMenu/ContextMenuButtonRenderer.cs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using Android.App;
45
using Android.Content;
6+
using Android.OS;
57
using Android.Support.V7.View.Menu;
68
using Android.Views;
79
using AndroidX.AppCompat.Widget;
@@ -11,16 +13,18 @@
1113
using Xamarin.Forms;
1214
using Xamarin.Forms.Internals;
1315
using Xamarin.Forms.Platform.Android;
16+
using Application = Android.App.Application;
1417

1518
[assembly: ExportRenderer(typeof(ContextMenuButton), typeof(ContextMenuButtonRenderer))]
1619

1720
namespace DIPS.Xamarin.UI.Android.ContextMenu
1821
{
19-
internal class ContextMenuButtonRenderer : ButtonRenderer, PopupMenu.IOnMenuItemClickListener
22+
internal class ContextMenuButtonRenderer : ButtonRenderer, PopupMenu.IOnMenuItemClickListener, Application.IActivityLifecycleCallbacks
2023
{
2124
private readonly Context m_context;
2225
private ContextMenuButton m_contextMenuButton;
2326
private Dictionary<ContextMenuItem, IMenuItem> m_menuItems;
27+
private MenuPopupHelper? m_menuHelper; //Might be null if the user never tapped the button to open it
2428

2529
public ContextMenuButtonRenderer(Context context) : base(context)
2630
{
@@ -40,11 +44,13 @@ protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
4044
{
4145
{
4246
contextMenuButton.Clicked += OpenContextMenu;
47+
(((Activity)Context!)).RegisterActivityLifecycleCallbacks(this);
4348
}
4449
}
4550
else
4651
{
4752
contextMenuButton.Clicked -= OpenContextMenu;
53+
(((Activity)Context!)).UnregisterActivityLifecycleCallbacks(this);
4854
}
4955
}
5056
}
@@ -58,10 +64,10 @@ private void OpenContextMenu(object sender, EventArgs e)
5864
m_menuItems = ContextMenuHelper.CreateMenuItems(m_context, m_contextMenuButton.ItemsSource,
5965
m_contextMenuButton, popupMenu);
6066
popupMenu.SetOnMenuItemClickListener(this);
61-
var menuHelper = new MenuPopupHelper(Context,(MenuBuilder) popupMenu.Menu, Control);
62-
menuHelper.Gravity = gravity;
63-
menuHelper.SetForceShowIcon(m_menuItems.Keys.Any(contextMenuItem => !string.IsNullOrEmpty(contextMenuItem.Icon) || !string.IsNullOrEmpty(contextMenuItem.AndroidOptions.IconResourceName))); //Show icons if there is any context menu items with a icon added
64-
menuHelper.Show();
67+
m_menuHelper = new MenuPopupHelper(Context,(MenuBuilder) popupMenu.Menu, Control);
68+
m_menuHelper.Gravity = gravity;
69+
m_menuHelper.SetForceShowIcon(m_menuItems.Keys.Any(contextMenuItem => !string.IsNullOrEmpty(contextMenuItem.Icon) || !string.IsNullOrEmpty(contextMenuItem.AndroidOptions.IconResourceName))); //Show icons if there is any context menu items with a icon added
70+
m_menuHelper.Show();
6571
m_contextMenuButton.SendContextMenuOpened();
6672
}
6773

@@ -98,5 +104,38 @@ public bool OnMenuItemClick(IMenuItem theTappedNativeItem)
98104

99105
return false;
100106
}
107+
108+
public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
109+
{
110+
111+
}
112+
113+
public void OnActivityDestroyed(Activity activity)
114+
{
115+
}
116+
117+
public void OnActivityPaused(Activity activity)
118+
{
119+
if (m_menuHelper is {IsShowing: true})
120+
{
121+
m_menuHelper.Dismiss();
122+
}
123+
}
124+
125+
public void OnActivityResumed(Activity activity)
126+
{
127+
}
128+
129+
public void OnActivitySaveInstanceState(Activity activity, Bundle outState)
130+
{
131+
}
132+
133+
public void OnActivityStarted(Activity activity)
134+
{
135+
}
136+
137+
public void OnActivityStopped(Activity activity)
138+
{
139+
}
101140
}
102141
}

src/DIPS.Xamarin.UI.Android/ContextMenu/ContextMenuHelper.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,14 @@ private static void UpdateMenuItem(Context context, ContextMenuButton contextMen
9292
if (!string.IsNullOrEmpty(contextMenuItem.Icon))
9393
{
9494
var id = context.Resources?.GetIdentifier(contextMenuItem.Icon, "drawable", context.PackageName);
95-
var androidResourceId = context.Resources?.GetIdentifier(contextMenuItem.AndroidOptions.IconResourceName, "drawable",context.PackageName);
96-
id = androidResourceId ?? id;
95+
if (!string.IsNullOrEmpty(contextMenuItem.AndroidOptions.IconResourceName))
96+
{
97+
var androidResourceId= context.Resources?.GetIdentifier(contextMenuItem.AndroidOptions.IconResourceName, "drawable",context.PackageName);
98+
if (androidResourceId != null)
99+
{
100+
id = androidResourceId;
101+
}
102+
}
97103
if (id != null)
98104
{
99105
menuItem.SetIcon((int)id);

src/DIPS.Xamarin.UI.iOS/ContextMenu/ContextMenuButtonRenderer.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using CoreGraphics;
66
using DIPS.Xamarin.UI.Controls.ContextMenu;
77
using DIPS.Xamarin.UI.iOS.ContextMenu;
8+
using Foundation;
89
using ObjCRuntime;
910
using UIKit;
1011
using Xamarin.Forms;
@@ -35,6 +36,11 @@ protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
3536
CreateMenu(); //Create the menu the first time so it shows up the first time the user taps the button
3637
Control.TouchDown += OnTouchDown;
3738
Control.ShowsMenuAsPrimaryAction = true;
39+
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidEnterBackgroundNotification, notification =>
40+
{
41+
Control.Menu = null;
42+
Control.Menu = CreateMenu(); //Recreate the menu to close it, and to make it possible to re-open it in one tap after it went to the background
43+
});
3844
}
3945
}
4046
}
@@ -43,6 +49,7 @@ protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
4349
if (Control != null)
4450
{
4551
Control.TouchDown -= OnTouchDown;
52+
NSNotificationCenter.DefaultCenter.RemoveObserver(UIApplication.DidEnterBackgroundNotification);
4653
}
4754
}
4855
}

0 commit comments

Comments
 (0)