Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Layout changes are not rendered without triggering a render cycle via interaction with UI #10539

Open
ewerspej opened this issue Oct 7, 2022 · 4 comments
Labels
area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter platform/android 🤖 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Milestone

Comments

@ewerspej
Copy link

ewerspej commented Oct 7, 2022

Description

I have a layout that I am optimizing for Portrait and Landscape modes respectively.

When I rotate the device, I change some layout values, such as the HorizontalOptions and VerticalOptions of certain Views that I would like to reposition in response to the size change for which I have an overide of OnSizeAllocated(). I am using the VisualStateManager to update the layout, but I've encountered exactly the same issue when I manually set the values in the code-behind or via bindings.

The problem is that there seems to be a render cycle missing after updating the layout. The changes only get applied when I add some UI interaction, such as a button press that triggers a PropertyChanged event on some property. This problem applies to all kinds of Views, such as Grids, StackLayouts, Labels and Buttons.

In the following example to reproduce the issue, there is a button that is centered at the bottom in Portrait mode and moved to the right hand-side when going into Landscape mode. The button only changes its position after pressing it instead of updating immediately:

XAML

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiViewUpdateBug.MainPage">

  <ContentPage.Resources>
    <ResourceDictionary>
      <Style x:Key="ButtonStyle" TargetType="Button">
        <Setter Property="Margin" Value="20" />
        <Setter Property="VisualStateManager.VisualStateGroups">
          <VisualStateGroupList>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Portrait">
                <VisualState.Setters>
                  <Setter Property="HorizontalOptions" Value="Center" />
                  <Setter Property="VerticalOptions" Value="End" />
                </VisualState.Setters>
              </VisualState>
              <VisualState x:Name="Landscape">
                <VisualState.Setters>
                  <Setter Property="HorizontalOptions" Value="End" />
                  <Setter Property="VerticalOptions" Value="Center" />
                </VisualState.Setters>
              </VisualState>
            </VisualStateGroup>
          </VisualStateGroupList>
        </Setter>
      </Style>
    </ResourceDictionary>
  </ContentPage.Resources>

  <Grid>

    <Label 
      x:Name="MyLabel"
      HorizontalOptions="Center"
      VerticalOptions="Center"
      Text="{Binding Clicks}"
      FontSize="150"/>

    <Button
      x:Name="MyButton"
      Text="Update"
      HeightRequest="80"
      WidthRequest="80"
      Clicked="MyButton_OnClicked"
      Style="{StaticResource ButtonStyle}"/>

  </Grid>

</ContentPage>

Code-behind

namespace MauiViewUpdateBug;

public partial class MainPage : ContentPage
{
    public int Clicks { get; set; }

    public MainPage()
    {
        InitializeComponent();
        BindingContext = this;
    }

    protected override void OnSizeAllocated(double width, double height)
    {
        base.OnSizeAllocated(width, height);

        VisualStateManager.GoToState(MyButton, width > height ? "Landscape" : "Portrait");
    }

    private void MyButton_OnClicked(object sender, EventArgs e)
    {
        Clicks++;
        OnPropertyChanged(nameof(Clicks));
    }
}

Note: This only occurs on Android, on iOS it works fine. This happens with real devices, not tested with emulators. I can reproduce this on Samsung S22 and S10 devices (at least).

Steps to Reproduce

  1. Create a new MAUI project
  2. Add the XAML and Code-behind like in the sample
  3. Run the App on an Android device
  4. Rotate the Device

Expected Behavior: The Button moves to the right in Landscape mode
Actual Behavior: The Button stays where it is and only updates its position after pressing it

Link to public reproduction project repository

https://github.com/ewerspej/dotnet-maui-bug-view-update

Version with bug

7.0.0-rc.1.22426.10

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 12.0

Did you find any workaround?

No

Relevant log output

No response

@ewerspej ewerspej added the t/bug Something isn't working label Oct 7, 2022
@jfversluis jfversluis added area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter platform/android 🤖 labels Oct 7, 2022
@jfversluis jfversluis added this to the Backlog milestone Oct 7, 2022
@ghost
Copy link

ghost commented Oct 7, 2022

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@BioTurboNick
Copy link
Contributor

I've encountered exactly this and it's quite frustrating. Child object is supposed to fit the final layout but it seems stuck with a value from a previous rendering pass. I had to refactor the whole thing to use another layout method to get it to work.

I'm willing to bet this is also why CarouselView changes its position and displays items in unexpected positions when the container shape changes or phone rotates.

@Zhanglirong-Winnie Zhanglirong-Winnie added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed labels Jul 17, 2023
@Zhanglirong-Winnie
Copy link

Verified this issue with Visual Studio Enterprise 17.7.0 Preview 3.0(net8). Can repro on android platform with sample project.
dotnet-maui-bug.zip
Screenshot 2023-07-17 151143
Screenshot 2023-07-17 151200

@BeepBeepBopBop
Copy link

I am experiencing issues with layout changes on Android as well. There are several contexts where a layout can not be updated dynamically, for example when applying a ControlTemplate to an element (whose child elements layout are computed upon appearing).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter platform/android 🤖 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants