PrismLibrary / Prism

Prism is a framework for building loosely coupled, maintainable, and testable XAML applications in WPF, Xamarin Forms, and Uno / Win UI Applications..

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tab Navigation working in iOS but not Android[BUG]

jamesv-7 opened this issue · comments

Description

I have a More menu and I need to navigate to home tab then navigate to a create account page. All works in iOS but not Android. This worked in Xamarin forms but not MAUI.

Here is a link to the repo - https://github.com/jamesv-7/PrismSelectTabAndNavigate

Steps to Reproduce

Use the linked repo and navigate to the More Menu Tab and select the button Navigate Tab Async. This should take you to home page tab then navigate you to the create account page. When you hit the back arrow to navigate backwards the app crashes.

Platform with bug

.NET MAUI

Affected platforms

Android

Did you find any workaround?

No workaround

Relevant log output

Here is the stack trace

Java.Lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at at android.view.ViewGroup.addViewInner(ViewGroup.java:6065)
at at android.view.ViewGroup.addView(ViewGroup.java:5884)
at at androidx.fragment.app.FragmentContainerView.addView(FragmentContainerView.kt:272)
at at android.view.ViewGroup.addView(ViewGroup.java:5824)
at at androidx.fragment.app.FragmentStateManager.addViewToContainer(FragmentStateManager.java:880)
at at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:565)
at at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:272)
at at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1934)
at at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1845)
at at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1782)
at at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:565)
at at android.os.Handler.handleCallback(Handler.java:938)
at at android.os.Handler.dispatchMessage(Handler.java:99)
at at android.os.Looper.loop(Looper.java:246)
at at android.app.ActivityThread.main(ActivityThread.java:8633)
at at java.lang.reflect.Method.invoke(Native Method)
at at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

@dansiegel any news on this?

We need to go to production within a month or so and cannot with out android working.

When will Prism Maui be out of prerelease?

TBH I haven't even looked at this yet and couldn't tell you when I'll be able to make time to. Issues like this tend to overwhelmingly be MAUI bugs and not Prism bugs.

That said you may want to use the Navigation Builder to build your Navigation Uri because the behavior for nesting tabs in a NavigationPage has changed in Maui.

@dansiegel

I used NavigationBuilder like below - but if you have more than 3 tabs you cannot navigate to the tab then onto another page. Less than 4 seems to work perfectly. Linked project updated. See below

        NavigationService.CreateBuilder().UseAbsoluteNavigation()
                    .AddTabbedSegment(nameof(MainTabbedPage), b =>
                        b
                         .CreateTab(t => t.AddNavigationPage().AddSegment("HomePage"))
                         .CreateTab(t => t.AddNavigationPage().AddSegment("ChestPage"))
                         .CreateTab(t => t.AddNavigationPage().AddSegment("PricePage"))
                         .CreateTab(t => t.AddNavigationPage().AddSegment("FoodPage"))
                         .CreateTab(t => t.AddNavigationPage().AddSegment("MoreMenuItemsPage"))
                         ).Navigate();
    }

public static readonly BindableProperty SelectedTabIndexProperty =
    BindableProperty.Create(
        nameof(SelectedTabIndex),
        typeof(int),
        typeof(BottomBarPage),
        0,
        BindingMode.TwoWay,
        null,
        propertyChanged: OnSelectedTabIndexChanged);

Navigat to tab:
index is coming form OnSelectedTabIndexChanged method

var navigationPage = (NavigationPage)tabbedPage.Children[index];
tabbedPage.CurrentPage = navigationPage;
var rootPage = navigationPage.RootPage as ITabRootPage;
rootPage.NavigationService.GoBackToRootAsync();

Navigate to Sub Page not working with more than 4 tabs
var navigationPage = CurrentPage as NavigationPage;
if (navigationPage?.RootPage is ITabRootPage rootPage)
{
if (IsRootPage(pageName))
await rootPage.NavigationService.GoBackToRootAsync(parameters);
else
{
Thread.Sleep(1000);
await rootPage.NavigationService.NavigateAsync(pageName, parameters);
}
}

@dansiegel if we buy a Commercial or Commercial Plus license would you be willing to fix this. If not were going to have to remove prism and go with an alternate solution.

Purchasing a license does not guarantee an issue will be fixed before our other tasks. However, we do give Commercial Plus license holders more priority over all others.

Looking very briefly at your code, I can see some very poor design choices that could easily be causing your problems. You should never be passing around the container like that and storing it in a base class, then use it to resolve navigation services. Even the way you are trying to have a different service class use and manage the Prism NavigationService is worrisome to me.

Based on just what my eyes can see, I would lean towards this being an application-code issue. Of course I have not verified this with your sample, but we do have unit tests covering tabbed navigation that are all passing.

I would recommend creating a more simplified version of this navigation pattern without all your infrastructure code and with the VM's using the Prism navigation services directly and see if you can reproduce the issue. Just a bare bones navigate to this page/navigate to that page sample. If it works, then you know it's something in your code.

@dansiegel

So I built a nuget package from the master repo with the following SelectTabAsync - this is not available in nuget store yet for Prism.Maui

feat: add ability to select tab and navigate - 22ad326

Task SelectTabAsync(string name, Uri uri, INavigationParameters parameters);

and I get the same results with 5 tabs as before. All works with 3 tabs but not 5.

Exception: An unsupported event occurred while Navigating. The attempted Navigation Stack is not supported by .NET MAUI

Navigation Code: works fine with 3 tabs but not 5 tabs

await NavigationService.SelectTabAsync(UIConstants.HomePage, new Uri(UIConstants.CreateAccountPage, UriKind.Relative));

I have create a very scaled down project that just has 5 tabs and a create account page to review - https://github.com/jamesv-7/PrismSelectTabAndNavigate - this uses Prism.Maui 9.0.480-pre which is not released yet.

For Android SelectTabAsync does not work with more that 3 tabs and iOS you have to manually select that tab but once you do it is navigated to the sub page.

So I ported the test project - https://github.com/jamesv-7/PrismSelectTabAndNavigate - to FreshMVVM in a separate branch and I have the same select tab and navigate issue with more than 3 tabs. So it seems it is a MAUI issue. I then tried AppShell Navigation and all works as expected. We will be porting our project from Prism.MAUI to AppShell Navigation.