dotnet / dotnet/maui

[Android] ScrollView clips its content at the safe-area inset padding while scrolling (iOS scrolls content under the inset)

Open
#37,306 1 comment 1 reaction 0 assignees View on GitHub
area-controls-scrollview area-safearea platform/android s/triaged s/verified
Dominant language
C#
Stars
23.3k
Forks
2k
Avg merge
1d 15h
Merged PRs (30d)
290

Description

### Description

On Android, a `ScrollView` that receives safe-area padding (net10 `SafeAreaEdges`, edge-to-edge) **clips its content at the padding line while scrolling**: the scrollable content never draws inside the inset band, even though the `ScrollView`'s own background extends to the physical screen edge. On iOS the same setup behaves like `UIScrollView` content insets: content scrolls THROUGH the inset band and the inset only guarantees that the end of the content rests clear of the system bars.

This breaks the standard edge-to-edge design where list content is expected to slide under translucent/floating chrome (gesture bar, floating tab bars) while scrolling.

### Steps to Reproduce

`dotnet new maui` (net10.0-android, MAUI 10.0.90), then:

**MainPage.xaml**

```xml




```

**MainPage.xaml.cs**

```csharp
public MainPage()
{
InitializeComponent();

for (var i = 0; i < 30; i++)
{
Stack.Add(new Border
{
StrokeThickness = 0,
HeightRequest = 56,
BackgroundColor = Colors.White,
Content = new Label { Text = $"Item {i}", VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center }
});
}
}
```

Scroll to the middle of the list and look at the bottom of the screen:

- the amber `ScrollView` background reaches the physical bottom edge (correct, page is edge-to-edge);
- the white items are **truncated at the safe-area padding line** (~the gesture-navigation inset) — pixel-sampling shows a permanent content-free amber band above the screen bottom at every mid-scroll position;
- on iOS the items scroll through that band and only the resting position clears the inset.

The effect is much more visible with a larger bottom inset contribution (e.g. a floating tab bar that augments the page's safe area): the content visibly "hits an invisible wall" well above the bar instead of sliding underneath it.

### Root cause / expected behavior

The safe-area inset is applied as **padding** on the native scroll container, and Android's default `clipToPadding=true` clips children at it. For safe-area-derived padding the expected semantics are iOS's content-inset ones: draw under, clear at rest. Setting `clipToPadding=false` on the platform view restores exactly that behavior.

### Workaround

```csharp
#if ANDROID
ScrollViewHandler.Mapper.AppendToMapping("NoClipToPadding", (handler, view) =>
{
if (handler.PlatformView is Android.Views.ViewGroup viewGroup)
{
viewGroup.SetClipToPadding(false);
}
});
#endif
```

Verified: with this mapping the content slides under the inset band while scrolling and still comes to rest clear of it (the padding continues to size the scroll range correctly).

### Version with bug

.NET MAUI 10.0.90, `net10.0-android`, Android API 36 emulator (gesture navigation).

### Affected platforms

Android (iOS behaves correctly; Windows not verified).

Contributor guide

Open the contributing guide

Research direction

Start with the Android ScrollView platform view and the MAUI safe-area padding path described in the issue; reproduce the behavior with the supplied MainPage.xaml and MainPage.xaml.cs sample on net10.0-android. Compare the default clip-to-padding behavior with the documented workaround, then run the relevant Android ScrollView tests if present. Done means content scrolls through the inset while the resting end remains clear of system bars.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, csharp
Domain
mobile
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.