Flicker/delay happens while navigating to some other page on click of menu item in MasterDetail Page

Hi all,
I am using a Master detail Page in my xamarin forms project and its having a few items in slide out menu which opens some other page on their click event.
I am using the same approch which is given in xmarin site like :

public void PopulateSildeOutMenu()
{
string path = Helpers.Settings.getSettings ("ProfileImage");
if (String.IsNullOrEmpty (path)) {
path = "default.jpg";
}

        cand_dashboard_slideOutMenu_profileImage.FileSource = path;

        var slideOutMenuItems1 = new List<SlideOutMenuItem> ();
        slideOutMenuItems1.Add (new SlideOutMenuItem {
            Title = "Dashboard",
            IconSource = "dashboard.png",
            TargetType = typeof(DashboardHome)
        });
        slideOutMenuItems1.Add (new SlideOutMenuItem {
            Title = "Notifications",
            IconSource = "notifications.png",
            TargetType = typeof(DashboardHome)
        });
        slideOutMenuItems1.Add (new SlideOutMenuItem {
            Title = "My Profile",
            IconSource = "my_profile.png",
            TargetType = typeof(Profile)
        });

}

above code is in my slideout page and following in Masterdetail Page :

public partial class MasterDetail : MasterDetailPage
{

    public MasterDetail()
    {
        InitializeComponent ();
        NavigationPage.SetHasNavigationBar (this, false);
        slideOutMenu.ItemList1.ItemSelected += OnItemSelected;

    }


    async void OnItemSelected (object sender, SelectedItemChangedEventArgs e)
    {
        var item = e.SelectedItem as SlideOutMenuItem;
        if (item != null) {

                    Detail = new NavigationPage((Page)Activator.CreateInstance(item.TargetType));
                    slideOutMenu.ItemList1.SelectedItem = null;
            IsPresented = false;
        }
    }
}

The above code works fine for me when I am navigating to other page in iOS but, same code creats a flicker/delay in opening next page while using in Android i.e. Page doesn't loads instantly. Any solution for that.. ?
Please suggest something, Thanks.

Answers

  • AdamPAdamP AUUniversity ✭✭✭✭✭

    @AmitKumar.8556 - Just to try and see if we can get an easy win, have you enabled Xaml Compilation on your device?

  • ArindamPalArindamPal USMember
    edited October 2016

    I am facing the same problem, uwp works ok, but there is a jarry experience for android. More the number of views in the page, more is the lag. It takes less than a second to load, but mars the experience. Will probably do better to reduce the number of view elements. Hoping this issue to be taken up in the subsequent xamarin form stable release.

    And xamlc is enabled on assembly level in our dev code.

  • testtest.2325testtest.2325 USMember

    @AdamP hi i m using XamlCompilation and facing the same issue. In fact removing that also make any effect.

  • AdamPAdamP AUUniversity ✭✭✭✭✭

    There are a few things that could cause a flicker.

    First, it is best to set Animate = true when doing a PushAsync(). This allows an animated transition.

    Next, there will be an issue with a flicker, if you are changing the MainPage or if the MasterDetailPage is inside a navigation page. If you change a page inside a navigation page inside the Detail section of your MDP, then everything should run smoothly, as it's programmed to wait for the slideout menu to move to the side before it changes it's detail page.

    However if you are completely replacing the MDP, this doesn't happen, and you will get a flicker / bad experience as it tries to push the menu back in, while changing the page.

    The only alternative to that route, is to wait for approx 1 second, until the menu slides away, then change the page.

  • FonagerFonager DKMember ✭✭

    @AmitKumar.8556 - did you find any solution to this?

  • For anyone else still encountering this nagging issue.
    The problem, I think, is that most examples we've seen for NavigationPage is simply not giving the full picture.
    Basically, MasterDetailPage goes under NavigationPage, and not the other way around.
    Here's an example (with no flickering under Android 5.1).

    public App()
    {
        InitializeComponent();
    
        MainPage = new NavigationPage(new MainPage());
    }
    
    <MasterDetailPage
        x:Class="MainPage"
        xmlns="...forms"
        xmlns:x="...xaml"
        BindingContext="{Binding Main, Source={StaticResource ViewModelLocator}}"
        Title="{Binding SelectedItem.Title}"
        >
        <MasterDetailPage.Master>
            <ListView
                ItemsSource="{Binding MenuItems}"
                SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                ItemSelected="MenuList_Selected"
                ItemTapped="MenuList_Tapped"
                />
        </MasterDetailPage.Master>
        <MasterDetailPage.Detail>
            <NavigationPage />
        </MasterDetailPage.Detail>
    </MasterDetailPage>
    
    public MainPage()
    {
        // initialize pages (page types are instantiated on view model locator)
        _pages.Add(typeof(WorksViewModel), (Page)Activator.CreateInstance(typeof(WorksPage)));
        _pages.Add(typeof(AboutViewModel), (Page)Activator.CreateInstance(typeof(AboutPage)));
    
        // initialize ui
        InitializeComponent();
    
        // load initial view (initial page is selected on view model - notice: Mode=TwoWay)
        Detail = _pages[_pageType];
    }
    
    private Type _pageType;
    private Dictionary<Type, Page> _pages = new Dictionary<Type, Page>();
    
    private void MenuList_Selected(object sender, SelectedItemChangedEventArgs args)
    {
        _pageType = args.SelectedItem.GetType();
    
        // load selection view
        Detail = _pages[_pageType];
    }
    
    private void MenuList_Tapped(object sender, ItemTappedEventArgs e)
    {
        // close menu
        IsPresented = false;
    }
    
  • PeterMarshPeterMarsh FRMember ✭✭

    I ran into this problem today and I have found a solution that has worked for me (Only tested on Android). After some fiddling, I noticed that when changing pages the Android splash screen is briefly shown (don't really know why unless it is always in the background of the application).

    I was using the default example code of the Master Detail page, which looks like this:

    private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
            if (!(e.SelectedItem is ContentPage item))
                return;
    
    
            Detail = new NavigationPage(page);
            IsPresented = false; 
    
            MasterPage.ListView.SelectedItem = null;
    }
    

    Based on a hunch, creating the new NavigationPage firstly removes the current Navigation and replaces it and must show whatever is in the background, in this case the splash screen. This creates the flicker effect.

    Here is what I've done to correct this:

    private async void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
            if (!(e.SelectedItem is ContentPage item))
                return;
    
    
            var root = Detail.Navigation.NavigationStack[0];
            Detail.Navigation.InsertPageBefore((Page)Activator.CreateInstance(item.GetType()), root);
            await Detail.Navigation.PopToRootAsync();
    
            IsPresented = false; 
    
            MasterPage.ListView.SelectedItem = null;
    }
    

    I insert the new page before the Root page of the Navigation and then pop all the other pages.

    Xamarin: 2.5.1.444934
    Minimum Android version: 4.0.3
    Target Android version: 8.0

    Hope this helps.

  • BrianAdamsBrianAdams Member

    Hi, I'm going to post to this thread even though the issue I'm seeing is not MDP driven but there has been discussion that this issue affects non-MDP NavigationPages also, which is my problem. I'm using the Navigation Service provided in the .NET Application Architecture for Xamarin
    Here is the GitHub Path (I'm too new to post links! ) dotnet-architecture/eShopOnContainers/blob/dev/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Navigation/NavigationService.cs

    This has the flicker:

    private async Task InternalNavigateToAsync(Type viewModelType, object parameter)
    {
    Page page = CreatePage(viewModelType, parameter);

            if (page is LoginView)
            {
                Application.Current.MainPage = new CustomNavigationView(page);
            }
            else
            {
                var navigationPage = Application.Current.MainPage as CustomNavigationView;
                if (navigationPage != null)
                {
                    await navigationPage.PushAsync(page);
                }
                else
                {
                    Application.Current.MainPage = new CustomNavigationView(page);
                }
            }
    
            await (page.BindingContext as ViewModelBase).InitializeAsync(parameter);
        }
    

    Forgive me if I've done this wrong but here is my interpretation of the above workaround for non-MDP navigation. The problem is that I am still seeing the flicker. Can I get some feedback on how to fix this?

    private async Task InternalNavigateToAsync(Type viewModelType, object parameter)
    {
    Page page = CreatePage(viewModelType, parameter);

            var navigationPage = Application.Current.MainPage as CustomNavigationView;
            if (navigationPage != null && navigationPage.Navigation != null) //Nav is null on initial app load
            {
                var root = navigationPage.Navigation.NavigationStack[0];
                if(parameter == null)
        {
                        navigationPage.Navigation.InsertPageBefore((Page)Activator.CreateInstance(page.GetType()), root);
    
        }else{
    
            navigationPage.Navigation.InsertPageBefore((Page)Activator.CreateInstance(page.GetType(), parameter), root);
                 }
                await navigationPage.Navigation.PopToRootAsync();
    
            }else{
                Application.Current.MainPage = new CustomNavigationView(page);
                await (page.BindingContext as ViewModelBase).InitializeAsync(parameter);
            }
    

    }

    Thank you,
    Brian

Sign In or Register to comment.