Why Pages are Flickering?

JassimRahmaJassimRahma USMember ✭✭✭
edited November 10 in Xamarin.Forms

Hi,

I have below code and I want when a user clicks on a button to view a page just like Facebook and twitter navigation but the pages are flickering when navigating as you can see in this video:

https://softnames.com/temp/Flickering.mov

This is happening on Android emulator and physical device.

What could be the reason?

Thanks,
Jassim

Best Answer

Answers

  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭
    edited November 11

    @JassimRahma - Cannot see your code. However, watched your movie. It looks like it is just the time taken to build and render the page, rather than flicker (rendering it more than once, possibly as a result of changing the size of a VisualElement in your own code). However, do make sure that you do not change the UI hierarchy after assigning the Content property of your ContentPage, unless there is a particular need to do so. Make assigning the Content property the last thing you do that changes the UI hierarchy as part of your page construction. (I'm simplifying when saying that, but that's the gist).

    Unfortunately, I don't know of any way in Xamarin.Forms to render a page to a separate piece of memory, and only once complete swap that block of memory with the memory used for the actual visible UI.

    It is possible to build a page not on the UI thread and only hook it up to the UI at the last moment, but that does not change the time taken to render the page.

  • JassimRahmaJassimRahma USMember ✭✭✭
    edited November 11

    My code for navigation in the App.xaml.cs is just like this for all buttons:

    void ShowMerchentProfile(object sender, EventArgs args)
    {
        MainPage = new ZeeraMerchent();
    }
    

    and my App,xaml is:

    <?xml version="1.0" encoding="utf-8"?>
    <Application xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="Zeera.App">
        <Application.Resources>
        <ResourceDictionary>
        <ControlTemplate x:Key="MainPageTemplate">
            <StackLayout>
                <!-- Header -->
                <StackLayout Orientation="Horizontal" VerticalOptions="Start" BackgroundColor="Black">
                    <Frame OutlineColor="Gray" HorizontalOptions="FillAndExpand" Margin="0" Padding="5" HasShadow="false">
                        <Grid RowSpacing="0" ColumnSpacing="0">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
    
                        <Image x:Name="backgwwwroundIzxxxxmag5e3" Source="http://allaboutiweb.com/wp-content/uploads/2014/04/callus@2x.png" HorizontalOptions="Start" HeightRequest="50" WidthRequest="50" Grid.Row="0" Grid.Column="0">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="ShowSettings" NumberOfTapsRequired="1" />
                        </Image.GestureRecognizers>
                        </Image>
    
                        <Label Text="Costa Coffee" HorizontalOptions="FillAndExpand" VerticalOptions="Center" TextColor="Black" Grid.Row="0" Grid.Column="1" />
    
                        <Image x:Name="backgwwwroundIm22344frrag5e3" Source="http://allaboutiweb.com/wp-content/uploads/2014/04/callus@2x.png" HorizontalOptions="End" HeightRequest="50" WidthRequest="50" Grid.Row="0" Grid.Column="2">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="ShowContact" NumberOfTapsRequired="1" />
                        </Image.GestureRecognizers>
                        </Image>
                        </Grid>
                    </Frame>
                </StackLayout>
    
                <!-- Content -->
                <ScrollView VerticalOptions="StartAndExpand" Padding="20">
                    <ContentPresenter />
                </ScrollView>
    
                <!-- Footer -->
                <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="End" Margin="0" Padding="0">
                    <Frame OutlineColor="Gray" HorizontalOptions="FillAndExpand" Margin="0" Padding="5" HasShadow="false">
                        <Grid RowSpacing="0" ColumnSpacing="0">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="50" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
    
                        <Image x:Name="backgwwwroundImag5e3" Source="http://allaboutiweb.com/wp-content/uploads/2014/04/callus@2x.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="0">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="ShowItems" NumberOfTapsRequired="1" />
                        </Image.GestureRecognizers>
                        </Image>
    
                        <Image x:Name="backgwwwro2opundImag5e3" Source="http://allaboutiweb.com/wp-content/uploads/2014/04/callus@2x.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="1">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="ShowMerchentProfile" NumberOfTapsRequired="1" />
                        </Image.GestureRecognizers>
                        </Image>
    
                        <Image x:Name="backgroundImas96ag5e3" Source="qr_code.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="2">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="ShowScanner" NumberOfTapsRequired="1" />
                        </Image.GestureRecognizers>
                        </Image>
    
                        <Image x:Name="backgroundI454mag5e3" Source="http://allaboutiweb.com/wp-content/uploads/2014/04/callus@2x.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="3">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="ShowOffers" NumberOfTapsRequired="1" />
                        </Image.GestureRecognizers>
                        </Image>
    
                        <Image x:Name="backgroundIm173ag5e3" Source="http://allaboutiweb.com/wp-content/uploads/2014/04/callus@2x.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="4">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="ShowMy" NumberOfTapsRequired="1" />
                        </Image.GestureRecognizers>
                        </Image>
                        </Grid>
                    </Frame>
                </StackLayout>
            </StackLayout>
        </ControlTemplate>
        </ResourceDictionary>
        </Application.Resources>
    </Application>
    
  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭
    edited November 11

    @JassimRahma

    What event results in ShowMerchentProfile being called?

    Can you show the code for the ZeeraMerchent constructor? And if ZeeraMerchent is a ContentPage, can you show the OnAppearing() code as well, if there is any?

    Is your "navigation" implemented purely by changing the App's MainPage? I've never tried doing that. If anybody else does that, perhaps they can confirm whether or not that might cause what you are calling flicker. Instinctively, it isn't something I would do, unless other alternatives prove problematic. If all of your pages have a standard header and footer, and it is just the part in the center that changes, and if you don't need hierarchical navigation or a back button, I would be tempted to either (a) just replace the center part rather than replace the whole page, or (b) have one page that contains all possible layouts, but using IsVisible to only show the appropriate one at any time.

  • JassimRahmaJassimRahma USMember ✭✭✭

    but this issue is only happening on Android and not iOS?

    Is there any way else to do it other than changing the MainPage? I don't want to see the Back button and I want it similar to the Facebook and twitter navigation without using the TabbedPage because I want the same style on all devices

    ShowMerchentProfile is:

    void ShowMerchentProfile(object sender, EventArgs args)
    {
        MainPage = new ZeeraMerchent();
    }
    

    and ZeeraMerchent is:

    using System;
    using System.Collections.Generic;
    
    using Xamarin.Forms;
    
    namespace Zeera
    {
        public partial class ZeeraMerchent : ContentPage
        {
            public ZeeraMerchent()
            {
                InitializeComponent();
            }
        }
    }
    
  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭
    edited November 11

    @JassimRahma

    What event results in ShowMerchentProfile being called?

    I've just quickly Googled "Xamarin.Forms changing MainPage". There are multiple hits, including some saying that it is fine to do this on iOS but not Android (including because of rendering issues). However, I found one thread where @AdamP says he does it without problem, so it is possible.

    Re. "Is there any way else to do it other than changing the MainPage?" - Yes. I listed two methods in my previous post.

  • JassimRahmaJassimRahma USMember ✭✭✭

    @JohnHardman said:
    @JassimRahma

    What event results in ShowMerchentProfile being called?

    Can you show the code for the ZeeraMerchent constructor? And if ZeeraMerchent is a ContentPage, can you show the OnAppearing() code as well, if there is any?

    Is your "navigation" implemented purely by changing the App's MainPage? I've never tried doing that. If anybody else does that, perhaps they can confirm whether or not that might cause what you are calling flicker. Instinctively, it isn't something I would do, unless other alternatives prove problematic. If all of your pages have a standard header and footer, and it is just the part in the center that changes, and if you don't need hierarchical navigation or a back button, I would be tempted to either (a) just replace the center part rather than replace the whole page, or (b) have one page that contains all possible layouts, but using IsVisible to only show the appropriate one at any time.

    How can I make option (a) which is changing the content without changing the header and footers?

    I actually thought my code is doing that and did not expected it will reload the whole page

  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭

    @JassimRahma - You are not providing enough information to be able to tell you what to change in your code.

    You said:

    My code for navigation in the App.xaml.cs is just like this for all buttons:
    
    void ShowMerchentProfile(object sender, EventArgs args)
    {
        MainPage = new ZeeraMerchent();
    }
    

    And have shown ZeeraMerchent as being a ContentPage.

    If, every time you want to navigate, you reassign MainPage, which is what you seem to be saying, you are indeed replacing the whole page, not part of a page.

    However, you have shown XAML for a ControlTemplate with a ContentPresenter, so the question is - are you reassigning MainPage, or are you actually changing the Content property of the ContentPresenter when you navigate?

    And, again, what event results in ShowMerchentProfile being called?

  • JassimRahmaJassimRahma USMember ✭✭✭

    sorry John, excuse for that because I am new to Xamarin.

    I create this App.xaml so it will be a template then I don't need to reload the whole page which it seems to be happening..

            <?xml version="1.0" encoding="utf-8"?>
            <Application xmlns="http://xamarin.com/schemas/2014/forms"
                xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                x:Class="Zeera.App">
                <Application.Resources>
                <ResourceDictionary>
                <ControlTemplate x:Key="MainPageTemplate">
                    <StackLayout>
                        <!-- Header -->
                        <StackLayout Orientation="Horizontal" VerticalOptions="Start" BackgroundColor="Black">
                            <Frame OutlineColor="Gray" HorizontalOptions="FillAndExpand" Margin="0" Padding="5" HasShadow="false">
                                <Grid RowSpacing="0" ColumnSpacing="0">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
    
                                <Image x:Name="backgwwwroundIzxxxxmag5e3" Source="settings.png" HorizontalOptions="Start" HeightRequest="50" WidthRequest="50" Grid.Row="0" Grid.Column="0">
                                <Image.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="ShowSettings" NumberOfTapsRequired="1" />
                                </Image.GestureRecognizers>
                                </Image>
    
                                <Label Text="Costa Coffee" HorizontalOptions="FillAndExpand" VerticalOptions="Center" TextColor="Black" Grid.Row="0" Grid.Column="1" />
    
                                <Image x:Name="backgwwwroundIm22344frrag5e3" Source="contact.png" HorizontalOptions="End" HeightRequest="50" WidthRequest="50" Grid.Row="0" Grid.Column="2">
                                <Image.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="ShowContact" NumberOfTapsRequired="1" />
                                </Image.GestureRecognizers>
                                </Image>
                                </Grid>
                            </Frame>
                        </StackLayout>
    
                        <!-- Content -->
                        <ScrollView VerticalOptions="StartAndExpand" Padding="20">
                            <ContentPresenter />
                        </ScrollView>
    
                        <!-- Footer -->
                        <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="End" Margin="0" Padding="0">
                            <Frame OutlineColor="Gray" HorizontalOptions="FillAndExpand" Margin="0" Padding="5" HasShadow="false">
                                <Grid RowSpacing="0" ColumnSpacing="0">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="50" />
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
    
                                <Image x:Name="backgwwwroundImag5e3" Source="items.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="0">
                                <Image.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="ShowItems" NumberOfTapsRequired="1" />
                                </Image.GestureRecognizers>
                                </Image>
    
                                <Image x:Name="backgwwwro2opundImag5e3" Source="profile.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="1">
                                <Image.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="ShowMerchentProfile" NumberOfTapsRequired="1" />
                                </Image.GestureRecognizers>
                                </Image>
    
                                <Image x:Name="backgroundImas96ag5e3" Source="scan.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="2">
                                <Image.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="ShowScanner" NumberOfTapsRequired="1" />
                                </Image.GestureRecognizers>
                                </Image>
    
                                <Image x:Name="backgroundI454mag5e3" Source="offers.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="3">
                                <Image.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="ShowOffers" NumberOfTapsRequired="1" />
                                </Image.GestureRecognizers>
                                </Image>
    
                                <Image x:Name="backgroundIm173ag5e3" Source="my.png" HeightRequest="30" WidthRequest="30" Grid.Row="0" Grid.Column="4">
                                <Image.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="ShowMy" NumberOfTapsRequired="1" />
                                </Image.GestureRecognizers>
                                </Image>
                                </Grid>
                            </Frame>
                        </StackLayout>
                    </StackLayout>
                </ControlTemplate>
                </ResourceDictionary>
                </Application.Resources>
            </Application>
    

    for every Image there is something like this:

    void ShowOffers(object sender, EventArgs args)
    {
        MainPage = new ZeeraOffers();
    }
    

    which I though (and I need it) to just load the content not the header and footer

    MerchentProfile (which is ZeeraMerchent) is:

    <?xml version="1.0" encoding="UTF-8"?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="Zeera.ZeeraMerchent"
        ControlTemplate="{StaticResource MainPageTemplate}">
        <ContentPage.Content>
            <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
                <Label Text="Merchent Profile" />
            </StackLayout>
        </ContentPage.Content>
    </ContentPage>
    

    and ZeeraOffers is:

    <?xml version="1.0" encoding="UTF-8"?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="Zeera.ZeeraOffers"
        ControlTemplate="{StaticResource MainPageTemplate}">
        <ContentPage.Content>
            <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
                <Label Text="Offers" />
            </StackLayout>
        </ContentPage.Content>
    </ContentPage>
    

    Hope the info is sufficient

  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭

    @JassimRahma - If I've understood that correctly, you are using a ControlTemplate to define a similar layout on different pages, but each time you reassign MainPage you are replacing the whole page, not just the bit in the middle. So the header is replaced, the center bit is replaced, and the footer is replaced. The ControlTemplate just means the header and footer looks the same on each page.

    If you just want the middle bit to be replaced, you don't reassign MainPage. Instead, you need to reassign the Content property of the ScrollView (or use IsVisible as mentioned previously). To do that, you'd need to restructure your code so that you have a single page rather than multiple pages, add a name to the ScrollView, then assign the Content of the named ScrollView in your code-behind.

  • JassimRahmaJassimRahma USMember ✭✭✭

    but is this what's happening when you use twitter app or Facebook app for example?

    they have the same layout, buttons on the footer and a header then only the center part is changing..

  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭

    @JassimRahma - I'd like to have the source code of Facebook and Twitter to study, but it's not open source. I can only therefore make educated guesses about how they work.

  • JassimRahmaJassimRahma USMember ✭✭✭

    Lol :0 what I meant is the look and feel because it doesn't seem t be a TabbedPaged, it's the same design on all platform and it's not flickering.. :)

  • JassimRahmaJassimRahma USMember ✭✭✭

    How can I you need to reassign the Content property using my above code? hope this will solve the problem..

  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭

    @JassimRahma - For how to name a XAML element and how to reference it from code-behind, see the Getting Started guide at https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/getting_started_with_xaml/ . Read the bit in that guide about x:Name

  • JassimRahmaJassimRahma USMember ✭✭✭

    I checked it John but can't find what I need. For example, if I want the below template where Header and footer is assigned in the App.xaml as per about code then how can I create and set the middle part of it so it will just show the About us, Contact us or Products without having to reload the whole page?

    Kindly advise..

    Thanks,
    Jassim

  • CharwakaCharwaka INMember ✭✭✭
  • JassimRahmaJassimRahma USMember ✭✭✭

    but how can I make the MasterDetailsPage to work like the mentioned scenario in the above image?

  • LewisKLewisK USUniversity ✭✭

    @JassimRahma said:
    but how can I make the MasterDetailsPage to work like the mentioned scenario in the above image?

    Im pretty sure that's not possible using forms code. You would have to use native things like fragments for android.

  • CharwakaCharwaka INMember ✭✭✭

    Hi @JassimRahma

    Do you want some thing like Sliding pages With Header Constant And Content changing ?

  • JassimRahmaJassimRahma USMember ✭✭✭

    Nope Please check above image to understand

  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭
    edited November 14

    @JassimRahma - Here you go. This should give you the basis of what you need to do. I've done it in C#, but converting it to XAML should be trivial.

    For the three middle sections, I've done two as StackLayouts and one as a ContentView, just to show that you can use anything there.

    You'll notice that the header and footer do not flicker when the middle changes.

    public class ChangingMiddlePageView : ContentPage
    {
        public ChangingMiddlePageView()
        {
            StackLayout contactUsSection = new StackLayout
            {
                BackgroundColor = Color.Black,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                Children =
                {
                    new Label
                    {
                        Text = "Contact Us",
                        HorizontalOptions = LayoutOptions.Center,
                        HorizontalTextAlignment = TextAlignment.Center,
                        BackgroundColor = Color.Black,
                        TextColor = Color.White
                    }
    
                }
            };
    
            // using a ContentView just for variety
            ContentView productsSection = new ContentView
            {
                BackgroundColor = Color.Black,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                Content = new Label
                {
                    Text = "Products",
                    HorizontalOptions = LayoutOptions.Center,
                    HorizontalTextAlignment = TextAlignment.Center,
                    BackgroundColor = Color.Black,
                    TextColor = Color.White
                }
            };
    
            StackLayout aboutUsSection = new StackLayout
            {
                BackgroundColor = Color.Black,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                Children =
                {
                    new Label
                    {
                        Text = "About Us",
                        HorizontalOptions = LayoutOptions.Center,
                        HorizontalTextAlignment = TextAlignment.Center,
                        BackgroundColor = Color.Black,
                        TextColor = Color.White
                    }
    
                }
            };
    
            ContentView middleView = new ContentView
            {
                Content = contactUsSection,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                BackgroundColor = Color.Black
            };
    
            this.Content = new StackLayout
            {
                Orientation = StackOrientation.Vertical,
                BackgroundColor = Color.Black,
                Children =
                {
                    new Label
                    {
                        Text = "Header",
                        BackgroundColor = Color.Pink,
                        TextColor = Color.White,
                        VerticalOptions = LayoutOptions.Start
                    },
                    middleView,
                    new StackLayout
                    {
                        Orientation = StackOrientation.Horizontal,
                        BackgroundColor = Color.Yellow,
                        VerticalOptions = LayoutOptions.End,
                        Children =
                        {
                            new Button
                            {
                                Text = "C",
                                BackgroundColor = Color.Blue,
                                TextColor = Color.White,
                                Command = new Command(() =>
                                {
                                    middleView.Content = contactUsSection;
                                })
                            },
                            new Button
                            {
                                Text = "P",
                                BackgroundColor = Color.Red,
                                TextColor = Color.White,
                                Command = new Command(() =>
                                {
                                    middleView.Content = productsSection;
                                })
                            },
                            new Button
                            {
                                Text = "A",
                                BackgroundColor = Color.Lime,
                                TextColor = Color.White,
                                Command = new Command(() =>
                                {
                                    middleView.Content = aboutUsSection;
                                })
                            },
                        }
                    }
                }
            };
        }
    }
    
  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭

    @JassimRahma - Did that help?

  • JassimRahmaJassimRahma USMember ✭✭✭

    But John, this way all the views will be in one file? so I will have about us, products, etc all in the same file which will make the code too long and mess..

    How can I have the same but in separate XAMLs then just call every XAML to view in the middle part?

Sign In or Register to comment.