A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
Hello @Sebastian Kruse ,
Thanks for your question.
When you set SafeAreaEdges on a view inside a CollectionView.GroupHeaderTemplate, it gets ignored. This is because SafeAreaEdges is only processed at the Page level or direct layout children, not inside DataTemplate items rendered by a CollectionView.
Since you already know iOS, I'll focus on Android. I recommend some following steps:
- Step 1: Create a shared interface
public interface ISafeAreaService
{
Thickness GetSafeAreaInsets();
}
- Step 2: Android implementation
// Platforms/Android/SafeAreaService.cs
using AndroidX.Core.View;
using Microsoft.Maui.Platform;
public class SafeAreaService : ISafeAreaService
{
public Thickness GetSafeAreaInsets()
{
var activity = Platform.CurrentActivity;
if (activity == null) return new Thickness(0);
var decorView = activity.Window?.DecorView;
if (decorView == null) return new Thickness(0);
var insets = ViewCompat.GetRootWindowInsets(decorView);
if (insets == null) return new Thickness(0);
var sysBars = insets.GetInsets(WindowInsetsCompat.Type.SystemBars());
var cutout = insets.DisplayCutout;
int cutoutTop = cutout?.SafeInsetTop ?? 0;
int cutoutBottom = cutout?.SafeInsetBottom ?? 0;
int cutoutLeft = cutout?.SafeInsetLeft ?? 0;
int cutoutRight = cutout?.SafeInsetRight ?? 0;
float density = activity.Resources.DisplayMetrics.Density;
return new Thickness(
Math.Max(sysBars.Left, cutoutLeft) / density,
Math.Max(sysBars.Top, cutoutTop) / density,
Math.Max(sysBars.Right, cutoutRight) / density,
Math.Max(sysBars.Bottom, cutoutBottom) / density
);
}
}
- Step 3: Register in
MauiProgram.cs
builder.Services.AddSingleton<ISafeAreaService, SafeAreaService>();
- Step 4: Use in your page and apply to group header
public partial class MyPage : ContentPage
{
private readonly ISafeAreaService _safeAreaService;
public MyPage(ISafeAreaService safeAreaService)
{
InitializeComponent();
_safeAreaService = safeAreaService;
}
protected override void OnAppearing()
{
base.OnAppearing();
var insets = _safeAreaService.GetSafeAreaInsets();
MyViewModel.GroupHeaderPadding = new Thickness(
insets.Left,
insets.Top,
insets.Right,
0
);
}
}
<ContentPage SafeAreaEdges="None">
<CollectionView ItemsSource="{Binding GroupedItems}"
IsGrouped="True">
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
<Grid Padding="{Binding Source={RelativeSource AncestorType={x:Type vm:MyViewModel}},
Path=GroupHeaderPadding}">
<Label Text="{Binding GroupName}"
FontSize="18"
FontAttributes="Bold"/>
</Grid>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Title}"/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>
Note: it's better to read insets in OnAppearing() and test on a real device
I hope this addresses your question. If this response was helpful, please consider following the guidance to provide feedback.