Skip to content
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

Fix: Accessibility with overlaying popups #136

Merged
merged 3 commits into from
Sep 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 55 additions & 21 deletions Mopups/Mopups.Maui/Platforms/Android/Impl/AndroidMopups.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ public static bool SendBackPressed(Action? backPressedHandler = null)
{
var popupNavigationInstance = MopupService.Instance;

if (popupNavigationInstance.PopupStack.Count > 0)
if(popupNavigationInstance.PopupStack.Count > 0)
{
var lastPage = popupNavigationInstance.PopupStack[popupNavigationInstance.PopupStack.Count - 1];

var isPreventClose = lastPage.SendBackButtonPressed();

if (!isPreventClose)
if(!isPreventClose)
{
popupNavigationInstance.PopAsync().SafeFireAndForget();
}
Expand All @@ -36,7 +36,7 @@ public static bool SendBackPressed(Action? backPressedHandler = null)

public Task AddAsync(PopupPage page)
{
HandleAccessibility(true, page.DisableAndroidAccessibilityHandling, page.Parent as Page);
HandleAccessibility(true, page.DisableAndroidAccessibilityHandling, page);

page.Parent = MauiApplication.Current.Application.Windows[0].Content as Element;
page.Parent ??= MauiApplication.Current.Application.Windows[0].Content as Element;
Expand All @@ -55,9 +55,9 @@ public Task RemoveAsync(PopupPage page)
{
var renderer = IPopupPlatform.GetOrCreateHandler<PopupPageHandler>(page);

if (renderer != null)
if(renderer != null)
{
HandleAccessibility(false, page.DisableAndroidAccessibilityHandling, page.Parent as Page);
HandleAccessibility(false, page.DisableAndroidAccessibilityHandling, page);

DecoreView?.RemoveView(renderer.PlatformView as Android.Views.View);
renderer.DisconnectHandler(); //?? no clue if works
Expand All @@ -70,47 +70,81 @@ public Task RemoveAsync(PopupPage page)
}

//! important keeps reference to pages that accessibility has applied to. This is so accessibility can be removed properly when popup is removed. #https://github.com/LuckyDucko/Mopups/issues/93
readonly List<Android.Views.View?> views = new();
void HandleAccessibility(bool showPopup, bool disableAccessibilityHandling, Page? mainPage = null)
readonly Dictionary<Type, List<Android.Views.View>> accessibilityStates = new();
void HandleAccessibility(bool showPopup, bool disableAccessibilityHandling, PopupPage popup)
{
if (disableAccessibilityHandling)
if(disableAccessibilityHandling)
{
return;
}

if (showPopup)
if(showPopup)
{
mainPage ??= Application.Current?.MainPage;
Page? mainPage = popup.Parent as Page ?? Application.Current?.MainPage;

if (mainPage is null)
if(mainPage is null)
{
return;
}

views.Add(mainPage.Handler?.PlatformView as Android.Views.View);
List<Android.Views.View> views = [];

var mainPageAndroidView = mainPage.Handler?.PlatformView as Android.Views.View;
if(mainPageAndroidView is not null && mainPageAndroidView.ImportantForAccessibility != ImportantForAccessibility.NoHideDescendants)
{
views.Add(mainPageAndroidView);
}

int navCount = mainPage.Navigation.NavigationStack.Count;
int modalCount = mainPage.Navigation.ModalStack.Count;
if(navCount > 0)
{
var androidView = mainPage.Navigation.NavigationStack[navCount - 1]?.Handler?.PlatformView as Android.Views.View;

if(androidView is not null && androidView.ImportantForAccessibility != ImportantForAccessibility.NoHideDescendants)
{
views.Add(androidView);
}
}

if (navCount > 0)
int modalCount = mainPage.Navigation.ModalStack.Count;
if(modalCount > 0)
{
views.Add(mainPage.Navigation?.NavigationStack[navCount - 1]?.Handler?.PlatformView as Android.Views.View);
var androidView = mainPage.Navigation.ModalStack[modalCount - 1]?.Handler?.PlatformView as Android.Views.View;
if(androidView is not null && androidView.ImportantForAccessibility != ImportantForAccessibility.NoHideDescendants)
{
views.Add(androidView);
}
}

if (modalCount > 0)
var popupCount = MopupService.Instance.PopupStack.Count;
if(popupCount > 1)
{
views.Add(mainPage.Navigation?.ModalStack[modalCount - 1]?.Handler?.PlatformView as Android.Views.View);
var androidView = MopupService.Instance.PopupStack[popupCount - 2]?.Handler?.PlatformView as Android.Views.View;
if(androidView is not null && androidView.ImportantForAccessibility != ImportantForAccessibility.NoHideDescendants)
{
views.Add(androidView);
}
}

accessibilityStates.Add(popup.GetType(), views);
}

foreach (var view in views)
if(accessibilityStates.ContainsKey(popup.GetType()))
{
ProcessView(showPopup, view);
foreach(var view in accessibilityStates[popup.GetType()])
{
ProcessView(showPopup, view);
}

if(!showPopup)
{
accessibilityStates.Remove(popup.GetType());
}
}

static void ProcessView(bool showPopup, Android.Views.View? view)
{
if (view is null)
if(view is null)
{
return;
}
Expand All @@ -126,7 +160,7 @@ static void ProcessView(bool showPopup, Android.Views.View? view)

static Task<bool> PostAsync(Android.Views.View? nativeView)
{
if (nativeView == null)
if(nativeView == null)
{
return Task.FromResult(true);
}
Expand Down
Loading