question

JesseKnott-2239 avatar image
0 Votes"
JesseKnott-2239 asked JarvanZhang-MSFT commented

Placing a static control that always maintains it's position.

In an attempt to make a free version of my app, I want to have ads that show if you are using the free version, and I want them to always be visible on the screen, even when a page consumes a long portion of a scrollview.
I know this would be accomplished with AbsoluteLayout But for the life of me, I cannot get one that will accomplish what I am looking for.

My desired effect is that a banner ad remain at the bottom of the screen, no matter where you go on the page. This ad, would be embeded into a View that I create which will check to see if you are using the free version, so in a paid version of the app, it was not visible, but I cannot get the ad to remain on the screen at all times. I can afix the ad to an absolute or relative position of the parent control, but have not had any luck with either one of two things happening.
1) the ad is behind the content of the page, and obscured/hidden.
2) the ad is afixed to the position on the page, and scrolls away with that portion of the page.

I know this is a simple task, I just haven't been able to produce it thus far with playing with the control.

Cheers!

dotnet-xamarin
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

JarvanZhang-MSFT avatar image
1 Vote"
JarvanZhang-MSFT answered JarvanZhang-MSFT commented

Hello,​

Welcome to our Microsoft Q&A platform!

For this function, try creating a page controlTemplate to define the page layout.

<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TestApplication_6"
             x:Class="TestApplication_6.App">
    <Application.Resources>
        <ControlTemplate x:Key="pageTemplate">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="0.9*" />
                    <RowDefinition Height="0.1*" />
                </Grid.RowDefinitions>
                <ContentPresenter Grid.Row="0"/>
                <StackLayout Grid.Row="1" BackgroundColor="LightBlue">
                    <!--display the ads-->
                </StackLayout>
            </Grid>
        </ControlTemplate>
    </Application.Resources>
</Application>

Then detect the identify to check if the user has paid for the application in the onAppearing method to consume the controlTemplate. If you want to display the ads on many pages, try to customize a ContentPage class to execute the code. Then make the other pages inherit from the custom page.

public class CustomPage : ContentPage
{
    protected override void OnAppearing()
    {
        base.OnAppearing();
        if (!App.IsPaidVerion)
        {
            this.ControlTemplate = App.Current.Resources["pageTemplate"] as ControlTemplate;
        }
    }
}

Here is the related doc, you could refer to:
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/control-template#substitute-content-into-a-contentpresenter

Best Regards,

Jarvan Zhang


If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


· 12
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Excellent! Thanks much!
Cheers!

0 Votes 0 ·

I'm sorry, I've been trying figure this out on my own, but haven't had much luck.
For some reason, the pages that get pushed to the ContentPresenter are not getting their ViewModel.

Here is what I tried, it seemed to nearly work, but in the end the page wasn't able to get the data from it's view model. The biggest problem with this approach is that it is statically coded to only work on the Home page only.

         <ContentPresenter BindingContext="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:Home}}}"Grid.Row="0" />

Is there a way to pass a reference to the Template? I could pass an instance of the viewModel when I instantiate the template, but I can't figure out how to do that.

I've also tried just creating a page that creates the layout, but I have a series with problems with that approach. Since it's a separate issue I'll create a thread for that one.
Cheers!

0 Votes 0 ·

Hi, JesseKnott-2239. We don't have to set binding for the 'ContentPresenter', it just represent the template of the page content. Please keep it as follows:

<ContentPresenter Grid.Row="0" />

I've checked your new thread, and reproduced the issue on my side. Sorry, it's my mistake. This is because the OnAppearing method is called after views' render, updating the template after view render causes losting the data. Please set BindingContext for the page in OnAppearing instead.

public partial class TestPage : CustomPage
{
    public TestViewModel viewModel;
    public TestPage()
    {
        InitializeComponent();

        viewModel = new TestViewModel();
        //BindingContext = viewModel;
    }
    protected override void OnAppearing()
    {
        base.OnAppearing();
        BindingContext = viewModel;
    }
}
0 Votes 0 ·

The only problem I have with this method, is that I cannot get the page to show as if it were being created by AdFrame.
The AdFrame is coded so that the ContentPresenter is in between two color boxes in my test. If I run it as written, I get the page that is based on AdFrame (`Home`) but the page doesn't have the two color boxes that are defined in AdFrame it's just the output of the Home page. If I comment out the InitializeComponent() in Home I get the page with the color boxes at the top and bottom. But the page content is never shown.
I tried playing with removing the InitializeComponent() from the AdFrame, but that has no effect at all.

I don't know if this is related somehow, but I am also getting this bizarre output in the debug output pane of VS

  [eglCodecCommon] setVertexArrayObject: set vao to 0 (0) 1 2
  [eglCodecCommon] setVertexArrayObject: set vao to 2 (2) 1 14
  [eglCodecCommon] setVertexArrayObject: set vao to 0 (0) 1 2
  [eglCodecCommon] setVertexArrayObject: set vao to 2 (2) 1 14

0 Votes 0 ·
Show more comments