Skip to content

[Android] RefreshView triggers pull-to-refresh immediately when scrolling up inside a WebView #33510

@pcdus

Description

@pcdus

Description

Context

I'm migrating a Xamarin.Forms application to .NET MAUI (.NET 10). The app displays web content inside a WebView wrapped in a RefreshView to allow users to manually refresh the page.

Expected Behavior

When the user scrolls up inside the WebView, the pull-to-refresh gesture should only trigger when the WebView content is already at the top (scroll position = 0). This is the standard behavior users expect, similar to how browsers or native apps handle pull-to-refresh with scrollable content.

Actual Behavior

On Android only, the pull-to-refresh is triggered immediately when the user scrolls up, even if the WebView content is not at the top. This makes it nearly impossible to scroll up through the web content without accidentally triggering a refresh.
iOS works correctly — the pull-to-refresh only activates when the WebView is scrolled to the top.

Steps to Reproduce

  1. Create a new MAUI application targeting Android and iOS
  2. Add a RefreshView containing a WebView
  3. Load a page with scrollable content (e.g., any news website)
  4. Scroll down in the WebView
  5. Try to scroll back up

Result on Android:

Pull-to-refresh indicator appears immediately when scrolling up, even when not at the top of the page.

Result on iOS:

Pull-to-refresh only triggers when the content is at the top.

Minimal Reproduction Code
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="MauiApp.MainPage">

    <RefreshView IsRefreshing="{Binding IsRefreshing}"
                 Command="{Binding RefreshCommand}">
        <WebView Source="https://example.com"
                 HorizontalOptions="Fill"
                 VerticalOptions="Fill" />
    </RefreshView>

</ContentPage>

ViewModel:

public partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    private bool isRefreshing;

    [RelayCommand]
    private async Task Refresh()
    {
        // Simulate refresh
        await Task.Delay(1000);
        IsRefreshing = false;
    }
}

Root Cause Analysis

After investigation, the issue seems to be related to how Android's SwipeRefreshLayout (which backs RefreshView on Android) determines whether its child content can scroll up.
SwipeRefreshLayout triggers pull-to-refresh when it believes the child "cannot scroll up" (i.e., is at the top). However, WebView is not recognized as a standard scrollable view by SwipeRefreshLayout, so it incorrectly assumes the content is always at the top.
On iOS, WKWebView is backed by UIScrollView, which correctly communicates its scroll state to the parent refresh control.

Environment

.NET Version: 10.0
MAUI Version: (latest as of January 2026)
IDE: Visual Studio 2022 / JetBrains Rider
Target OS: Android 14/15 (API 34/35)
Tested devices: Pixel emulator, Samsung Galaxy physical device

Related Issues

This appears to be a known limitation that was also present in Xamarin.Forms and may be related to:

The documented constraint that RefreshView expects a scrollable child (ScrollView, CollectionView, etc.)
WebView not being listed as a supported scrollable content type for RefreshView

Questions

Is this a known limitation or a bug?
Is there a recommended approach for using RefreshView with WebView on Android?
Are there plans to improve SwipeRefreshLayout integration with WebView in future MAUI releases?

Link to public reproduction project repository

No response

Version with bug

10.0.20

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

No response

Affected platforms

Android

Affected platform versions

No response

Did you find any workaround?

No response

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions