How to Make CarouselView Work with Pinch-to-Zoom in .NET MAUI
Amina Tariq

Amina Tariq @amina_taariq

Joined:
Feb 17, 2025

How to Make CarouselView Work with Pinch-to-Zoom in .NET MAUI

Publish Date: Jun 15
0 1

The CarouselView in .NET MAUI is a powerful control for building swipeable collections, perfect for galleries, tutorials, or sliders. But what if you want zoomable content—like images—inside each Carousel item?

This post walks you through combining CarouselView with a custom PinchToZoomContainer, enabling pinch-to-zoom and pan interactions inside carousel slides without breaking swipe navigation.

The Challenge
When you place a zoomable view inside a CarouselView, gesture conflicts arise:

  • Swiping to the next item vs. panning the zoomed content
  • Double-tap or pinch interfering with CarouselView's native swipe

If not handled carefully, users will either fail to zoom, or accidentally change slides while zooming. Our goal: smooth gestures without compromise.

The Building Block: PinchToZoomContainer

We use a custom ContentView (PinchToZoomContainer) that:

  • Handles pinch-to-zoom and double-tap
  • Allows panning only when zoomed in
  • Resets to original scale when zoomed out

Here's a quick recap of its structure:

public class PinchToZoomContainer : ContentView
{
    // Handles pinch, pan, and double-tap gestures
}
Enter fullscreen mode Exit fullscreen mode

It wraps your content (e.g., an image) and manages gestures smartly.
Integrating with CarouselView
Now, embed the PinchToZoomContainer in each carousel item:

<CarouselView ItemsSource="{Binding Images}">
    <CarouselView.ItemTemplate>
        <DataTemplate>
            <controls:PinchToZoomContainer>
                <Image Source="{Binding}" Aspect="AspectFit" />
            </controls:PinchToZoomContainer>
        </DataTemplate>
    </CarouselView.ItemTemplate>
</CarouselView>
Enter fullscreen mode Exit fullscreen mode

🔥 Key Idea: The zoom container manages gestures at the item level, allowing CarouselView to handle swipes only when the content is not zoomed in.

Gesture Conflict Handling
The magic happens in your zoom container’s pan gesture logic:

if (Content.Scale <= 1)
{
    return; // Let CarouselView handle the swipe
}
Enter fullscreen mode Exit fullscreen mode

This line ensures that:

  • Zoomed out: CarouselView handles swipe
  • Zoomed in: Only the content pans, swipe is blocked

Also, we dynamically add or remove pan gestures based on zoom state:

if (_currentScale > 1 && !GestureRecognizers.Contains(_panGesture))
{
    GestureRecognizers.Add(_panGesture);
}
Enter fullscreen mode Exit fullscreen mode

This keeps interactions natural and intuitive.

Full Example

Here’s a complete snippet

<CarouselView ItemsSource="{Binding ImageSources}">
    <CarouselView.ItemTemplate>
        <DataTemplate>
            <controls:PinchToZoomContainer>
                <Image Source="{Binding}" Aspect="AspectFit" />
            </controls:PinchToZoomContainer>
        </DataTemplate>
    </CarouselView.ItemTemplate>
</CarouselView>
Enter fullscreen mode Exit fullscreen mode

In the ViewModel:

public ObservableCollection<string> ImageSources { get; } = new()
{
    "image1.jpg",
    "image2.jpg",
    "image3.jpg"
};
Enter fullscreen mode Exit fullscreen mode

What Works Well

  • ✅ Pinch-to-zoom works seamlessly inside each slide
  • ✅ Swipe between slides only when not zoomed in
  • ✅ Double-tap toggles zoom
  • ✅ Panning stays within bounds

Wrap Up
You don’t have to choose between pinch-to-zoom and carousel swiping—you can have both! By isolating gestures within a PinchToZoomContainer and being smart about when panning is allowed, your users can enjoy a smooth, professional zoom gallery experience in .NET MAUI.

Check out the GitHub repo: PinchToZoomCarouselApp

Comments 1 total

  • SystemOperator
    SystemOperatorJun 15, 2025

    Great news! free tokens now live for Dev.to contributors to celebrate our authors' impact in Web3! Visit the claim page here (wallet connection required). – Dev.to Community Support

Add comment