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: Opt out of edge to edge enforcement on api 35+ #25517

Merged
merged 10 commits into from
Nov 1, 2024

Conversation

Redth
Copy link
Member

@Redth Redth commented Oct 24, 2024

Android 35+ enforces apps extending "Edge to Edge" by default. See #24742 for details.

For now, a better compromise is to disable this by default in MAUI apps, until we can provide better support for edge to edge within .NET MAUI itself as well as better safe area insets on Android.

If you still want to manually make your app more compatible with edge to edge, you can disable this implicit opt out by overriding the default theme, changing the maui_edgetoedge_optout attribute to false and the theme yourself:

<style name="MainThemeEdgeToEdge" parent="Maui.MainTheme.NoActionBar">
   <item name="maui_edgetoedge_optout">false</item>
</style>

And then applying the theme by calling it before the base.OnCreate(..) in your activity subclass (in the OnCreate method override):

protected override void OnCreate(Bundle? savedInstanceState)
{
    SetTheme(Resource.Style.MainThemeEdgeToEdge);

    base.OnCreate(savedInstanceState);
}

This also fixes a previous bug where we were always switching the theme based on the presence of the maui_splash attribute, not the actual value of the attribute.

Finally, it moves more calls into native android and reduces the boundary crossing for this specific method.

The new "Default" of opting out of the Edge to Edge enforcement on an Android 35+ device looks now like this:
Screenshot_1729819287

If you revert to the old behaviour by disabling the opt out, it will look like this:
Screenshot_1729819354

See #24742 for details.

It seems to be a better compromise to disable this by default in MAUI apps.  You can still opt out by including a similar style:

```xml
<style name="DisableOptOutEdgeToEdgeEnforcement">
   <item name="android:windowOptOutEdgeToEdgeEnforcement">false</item>
</style>
```

And then applying it in a similar way, either by calling it before the `base.OnCreate(..)` in your activity subclass (in the OnCreate method override), or by registering for the ActivityOnCreate lifecycle callback.

Eg:

```csharp
protected override void OnCreate(Bundle? savedInstanceState)
{
    // Disable Edge to Edge opt out by calling this before base.OnCreate()
    Theme?.ApplyStyle(Resource.Style.DisableOptOutEdgeToEdgeEnforcement, force: true);

    base.OnCreate(savedInstanceState);
}
```
@Redth Redth added this to the .NET 9.0 GA milestone Oct 24, 2024
@Redth Redth requested a review from a team as a code owner October 24, 2024 23:25
This will make it easier for devs to intentionally revert the implied opt-out of android 35 edge to edge enforcement behaviour that this PR also adds to MAUI.

Now all that's needed is to apply the disable style like this:

```csharp
protected override void OnCreate(Bundle? savedInstanceState)
{

	Theme?.ApplyStyle(Microsoft.Maui.Resource.Style.DisableOptOutEdgeToEdgeEnforcement, force: true);

	base.OnCreate(savedInstanceState);
}
```
@Redth Redth requested a review from PureWeen October 25, 2024 02:37
@Redth Redth modified the milestones: .NET 9.0 GA, .NET 9 SR1 Oct 28, 2024
@Redth Redth self-assigned this Oct 31, 2024
Redth added 6 commits October 31, 2024 10:21
This moves most of our MauiAppCompatActivity override into a platform interop method.

The other key change is switching how we check for the maui_splash attribute.  Previously we were really just resolving that it exists, not checking the actual value, so the theme was always going to be switched out.

This should 'fix' the splash attribute check.
We can now inherit the maui theme and override the `maui_edgetoedge_optout` value in the new theme and it will do the right thing.
Copy link
Member

@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks reasonable to me. I'm not sure we need a doc on how to override the theme, maybe just the next MAUI release notes would be fine?

@Redth
Copy link
Member Author

Redth commented Oct 31, 2024

This looks reasonable to me. I'm not sure we need a doc on how to override the theme, maybe just the next MAUI release notes would be fine?

I've added some notes to our release notes Loop to include when this gets merged and released. The notes are copied here below:

Android 15.0 (API 35) Edge to Edge Opt Out

When targeting apps on Android 15.0 (API 35), the default experience is now to force apps into "Edge to Edge" mode which means the app is responsible for reasoning about safe area insets and laying out content filling the entire screen.

Most existing .NET MAUI apps will benefit from opting out of Edge to Edge mode by default, and in .NET 9 SR1 we have made this the default experience in the Android themes for .NET MAUI. #25517

Future .NET MAUI updates will add better support for working with platform safe area insets and edge to edge experiences. If you want to override the .NET MAUI defaults now, you can extend the default MAUI theme and apply it in your app's activity.

First, create a new theme in your Platforms/Android/Resources/values/styles.xml file (you may need to create the file if it does not already exist):

<resources>
  <style name="MainThemeEdgeToEdge" parent="Maui.MainTheme.NoActionBar">
   <item name="maui_edgetoedge_optout">false</item>
  </style>
</resources>

Next, you can apply the theme in your Platforms/Android/MainActivity.cs by overriding the OnCreate(Bundle? savedInstanceState) method and applying your theme before the call to the base method:

protected override void OnCreate(Bundle? savedInstanceState)
{
    SetTheme(Resource.Style.MainThemeEdgeToEdge);

    base.OnCreate(savedInstanceState);
}

Now your app will extend to the full screen size of the device if your app is running on Android 35+.
If you're looking to make your app consistently expand to the full screen size, you may want to consider using the AndroidX helper API: EdgeToEdge.Enable(this) in your Activity's OnCreate which should enforce similar behavior on older devices.

@Redth Redth enabled auto-merge November 1, 2024 16:53
@@ -13,20 +14,12 @@ public partial class MauiAppCompatActivity : AppCompatActivity

protected override void OnCreate(Bundle? savedInstanceState)
{
if (!AllowFragmentRestore)
{
// Remove the automatically persisted fragment structure; we don't need them
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to move these comments?

@Redth Redth merged commit 1ddd9a0 into main Nov 1, 2024
107 checks passed
@Redth Redth deleted the dev/redth/android-edgetoedge-optout branch November 1, 2024 18:45
@github-actions github-actions bot locked and limited conversation to collaborators Dec 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants