Xamarin.Forms icon indicating copy to clipboard operation
Xamarin.Forms copied to clipboard

TabbedPage OnAppearing not called when navigated to page first time - android

Open LeoJHarris opened this issue 6 years ago • 30 comments

Description

When using tabbed page, the OnAppearing method is not always called. When I launch my app all the OnAppearing methods get called for the first time - fine. However when I navigate to another tabbed page the OnAppearing does not get called. Only when I navigate away and back to the tabbed page does the OnAppearing get called. I would expect the OnAppearing to be called anytime the page is appearing.

As a side note I checked and the OnDisappearing method does get called when navigating away from the page for the first time but OnAppearing not when navigating too first time.

Steps to Reproduce

  1. Launch app with two Tabbed Pages with the app landing on the first tabbed page.
  2. Navigate to 2nd tabbedpage first time - check OnAppearing method being called
  3. navigate back to first tabbed page and then back to 2nd tabbed page and OnAppearing method called

Expected Behavior

The 2nd tabbed page's OnAppearing method to be called upon first navigation to this page.

Actual Behavior

The 2nd tabbed page's OnAppearing method does not get called upon first navigation to this page.

Basic Information

  • Version with issue: 3.1.0.697729
  • Last known good version: NA
  • IDE: visual studio community 15.8.5 (windows)
  • Platform Target Frameworks:
    • Android: 9.0 (P)

Reproduction Link

Sample.zip

LeoJHarris avatar Sep 20 '18 21:09 LeoJHarris

Behavior as described on droid; When app loads, OnAppearing for tabbed page 1, which has yet to appear on screen, is fired. On iOS, the behavior is as expected. Tested on latest 3.3.0.

kingces95 avatar Sep 22 '18 00:09 kingces95

Do we have an ETA for this being fixed? It's having a material effect on behaviour in our project.

jameslavery-zz avatar Feb 08 '19 14:02 jameslavery-zz

Workaround: Use a simple messaging/notification system and send the notifications manually. Worked for me. In the attached zip there is an example of such a system.

Messenger.zip

AndreiLazarescu avatar Feb 12 '19 02:02 AndreiLazarescu

@AndreiLazarescu Thanks - I could also use the built-in MessagingCenter. How did you implement this to work around the problem? Do you send a message from an Event in the MvxTabbedPage itself? Bearing in mind that the OnAppearing event can't be used!

jameslavery-zz avatar Feb 12 '19 08:02 jameslavery-zz

@jameslavery I encourage you to use the build-in one, it was just as an example in order to avoid confusion with the push notifications. I completely removed the Appearing and Disappearing events and added an event handler on CurrentPageChanged in the TabbedPage. From there I am sending an "Appearing" and an "Disappearing" message with CurrentPage.BindingContext as an parameter. In each PageModel that is child of TabbedPage I have two handlers for those messages where I do a check. If BindingContext (the one sent as an parameter) is the same as my current model (the actual page itself) I do appearing, if not I do disappearing. I also added a flag in each page model that I make true when it is appearing and false when it is disappearing in order to not call the disappearing method for all pages each time a page changes. Below is the behavior:

  • Page1Model --> Appearing

  • Page2Model --> Appearing

  • Page1Model --> Disappearing

  • Page3Model --> Appearing

  • Page2Model --> Disappearing

  • Page2Model --> Appearing

  • Page3Model --> Disappearing

AndreiLazarescu avatar Feb 12 '19 13:02 AndreiLazarescu

@AndreiLazarescu Thanks - that makes sense. A pity to have to do all this work of course!

jameslavery-zz avatar Feb 12 '19 14:02 jameslavery-zz

@jameslavery Your welcome, glad I could help. Yes, that is true but Xamarin.Forms is still at an early stage, whit time it will mature and these kind of problems will go away. Best of luck with your project!

AndreiLazarescu avatar Feb 12 '19 15:02 AndreiLazarescu

Validated this here in https://github.com/jamesmontemagno/Hanselman.Forms

jamesmontemagno avatar Mar 02 '19 00:03 jamesmontemagno

Any update on this?

vjsystematix avatar Apr 01 '19 06:04 vjsystematix

I really need this fixed as well. Would love an update.

MortMH avatar Jun 29 '19 20:06 MortMH

I have the same issue with Xamarin Forms 3.4, encountered on Android 6.0.1 (Padfone S, Galaxy S4) and 8.1 (emulator). As a workaround, I subscribed to CurrentPageChanged of the tabbed page, check if it is showing the first child, then call a public method (which simply triggers OnAppearing()) on that child page. The workaround works well, but this issue definitely needs to be fixed.

ngoquoc avatar Jul 19 '19 07:07 ngoquoc

This is a curious one for me as well. I'm using Xamarin 4.4.0 and when running on Android, the behavior is not as I expected it. I expect when changing from Tab1 to Tab2 that Tab1.OnDisappearing() would fire and Tab2.OnAppearing() would fire after. This seems to happen when tapping on the tab on the navigation bar. However, when swiping left or right to change the tab, the Tab1.OnDisappearing() is delayed. It doesn't fire until there is a second swipe back to the original tab or on to a third tab. This is no good because I cannot predict the behavior of the user and I need to take action between tab changes.
Also, there is no tab tracking on the TabbedPage to tell me what tab I am changing from and to, only current. I only know the latest tab so I cannot force OnDisappearing() naturally from the TabbedPage. The OnAppearing and OnDisappering methods are private so you cannot call them directly from the TabbedPage.

As a workaround, I'm using a combination of an interface for the pages that require the behavior and overriding the TabbedPage to track the CurrentPage before it is changed.

public interface IShowable {
  void OnShow();
  void OnHide();
}
public partial class TestViewModel: IShowable 
{
  public void OnShow() { //DoSomething }
  public void OnHide() { //DoSomething }
}
public partial class MainPage:  TabbedPage
{
  private Xamarin.Forms.Page myCurrentPage;  
  protected override void OnCurrentPageChanged()
  {
    if(myCurrentPage.BindingContext is IShowable )
    {
      (myCurrentPage.BindingContext as IShowable ).OnHide();  
    }
    base.OnCurrentPageChanged(); 
    myCurrentPage = CurrentPage;   

    if(myCurrentPage.BindingContext is IShowable )
    {
      (myCurrentPage.BindingContext as IShowable ).OnShow();  
    }
}

You could apply the interface at the Page level.

It would be better if OnDisappear simply fired when the page disappears. Is there any plan for a fix?

tdcaesar avatar Jan 06 '20 13:01 tdcaesar

The Problem still exists roughly 1.5 years later..

kevin-mueller avatar Mar 26 '20 13:03 kevin-mueller

The issue still exists roughly 2 years later!!!!

FreakyAli avatar May 21 '20 05:05 FreakyAli

I noticed one more strange behaviour, I have TabbedPage with 5 tabs (ContentPage1|ContentPage2|ContentPage3|ContentPage4|NavigationPage/ContentPage5). When starting the app on iOS everything is as expected, OnAppearing on the 1st tab page is called. On Android I noticed that during startup also OnApearing from 5th tab is called, what is problematic.

RadoslawKubas avatar Jun 06 '20 07:06 RadoslawKubas

This very very big issue is still happening in latest XF 4.7 - ouch!

nbsoftware avatar Jun 30 '20 16:06 nbsoftware

Take the attached TabbedPageWithNavigationPage XF sample. Modified only to display the OnAppearing / OnDisappearing events

TabbedPageWithNavigationPage.zip

On Android, the events are totally not consistent:

Android

Launch
################## OnAppearing TodayPage
################## OnAppearing SchedulePage

Select tab "Schedule"
################## OnDisappearing TodayPage

Select tab "Settings"
################## OnAppearing SettingsPage
################## OnDisappearing SchedulePage

Select tab "Schedule"
################## OnAppearing SchedulePage
################## OnDisappearing SettingsPage

Select tab "Today"
################## OnAppearing TodayPage
################## OnDisappearing SchedulePage

It should be on par with iOS, which is consistent - even the order (OnDisappearing fired before the OnAppearing)

iOS

Launch
################## OnAppearing TodayPage

Select tab "Schedule"
################## OnDisappearing TodayPage
################## OnAppearing SchedulePage

Select tab "Settings"
################## OnDisappearing SchedulePage
################## OnAppearing SettingsPage

Select tab "Schedule"
################## OnDisappearing SettingsPage
################## OnAppearing SchedulePage

Select tab "Today"
################## OnDisappearing SchedulePage
################## OnAppearing TodayPage

Do you plan to fix the Android behavior very soon?

nbsoftware avatar Jul 01 '20 07:07 nbsoftware

I noticed one more strange behaviour, I have TabbedPage with 5 tabs (ContentPage1|ContentPage2|ContentPage3|ContentPage4|NavigationPage/ContentPage5). When starting the app on iOS everything is as expected, OnAppearing on the 1st tab page is called. On Android I noticed that during startup also OnApearing from 5th tab is called, what is problematic.

I concur. This is a regression because it worked at least in XF 3.5.0.169047 (the last known working version as far as I'm concerned

nbsoftware avatar Jul 01 '20 16:07 nbsoftware

I swear this was working as expected on my first deployment to the iOS App Store, but since then, somewhere along the way, has reverted to this buggy behaviour described here. Very frustrating when I had a tested working app, which I can no longer build as-is, and have to find a workaround for. ETA for a fix?

neoviz avatar Aug 25 '20 07:08 neoviz

same issue +1

codevon avatar Nov 05 '20 10:11 codevon

Same issue here in January 12 2021 with Xamarin Forms: 4.8.0.1269.

OrtizJorge97 avatar Jan 13 '21 05:01 OrtizJorge97

Same issue here on January 28th, 2021. Xamarin Forms 5.0.0.1874

Umer-Mahmood avatar Jan 28 '21 14:01 Umer-Mahmood

Same issue here on January 28th, 2021. Xamarin Forms 5.0.0.1874

@Umer-Mahmood how did you manage to solve it?

OrtizJorge97 avatar Jan 28 '21 15:01 OrtizJorge97

Override OnCurrentPageChanged in your TabbedPage and call a method in your page.

protected override void OnCurrentPageChanged() {
  base.OnCurrentPageChanged();
  var yourPage = (TodayPage)CurrentPage;
  yourPage.YourInitMhethod();
}

AlleSchonWeg avatar Jan 28 '21 17:01 AlleSchonWeg

This makes TabbedPage behavior very inconsistent between iOS and Android and is likely to confuse new Xamarin.Forms developers a lot. Fixing this should be high prio, considering for how long this issue has been around.

durandt avatar Feb 17 '21 10:02 durandt

I am waiting on this for more than a year!

smalgin avatar Mar 07 '21 02:03 smalgin

I'm using the latest version of XF 5 and the issue is still there. I have to add the following code in the CurrentPageChanged event to call the OnViewAppearing in the first tab of the views, this means that the first time the OnAppearing event is being call twice.

private readonly List<string> _pages = new List<string>();

private void MainPage_CurrentPageChanged(object sender, EventArgs e)
{
	var page = (CurrentPage as NavigationPage)?.RootPage;

	if (page == null) return;

	var pageName = page.GetType().Name;

	if (_pages.Contains(pageName).Equals(false))
	{
		_pages.Add(pageName);

		((ViewModelBase)page.BindingContext).OnViewAppearingAsync();
	}
}

Elinareso avatar Apr 24 '21 14:04 Elinareso

As a matter of fact, the healthy programming pattern with Xamarin UI is to expect things to be called multiple times.

For example, ComboBox IndexChanged event will be called multiple times during page appearance.

I use this safety check everywhere to avoid 'thrashing':

if (newIndex == _currentIndex)
    return;
. . .
if (newState.Equals(_currentState)
    return;

In some places it works well with Stateful (State) pattern (https://en.wikipedia.org/wiki/State_pattern)

smalgin avatar Apr 24 '21 15:04 smalgin

Still waiting for this

JorgeTorresPadron avatar Sep 16 '22 10:09 JorgeTorresPadron

@JorgeTorresPadron Have you tried MAUI?

AndreiLazarescu avatar Sep 16 '22 12:09 AndreiLazarescu