Add a pan gesture recognizer
The pan gesture is used for detecting the movement of fingers around the screen and applying that movement to content, and is implemented with the PanGestureRecognizer
class. A common scenario for the pan gesture is to horizontally and vertically pan an image, so that all of the image content can be viewed when it's being displayed in a viewport smaller than the image dimensions. This is accomplished by moving the image within the viewport, and is demonstrated in this article.
To make a user interface element moveable with the pan gesture, create a PanGestureRecognizer
instance, handle the PanUpdated
event, and add the new gesture recognizer to the GestureRecognizers
collection on the user interface element. The following code example shows a PanGestureRecognizer
attached to an Image
element:
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += (s, e) => {
// Handle the pan
};
image.GestureRecognizers.Add(panGesture);
This can also be achieved in XAML, as shown in the following code example:
<Image Source="MonoMonkey.jpg">
<Image.GestureRecognizers>
<PanGestureRecognizer PanUpdated="OnPanUpdated" />
</Image.GestureRecognizers>
</Image>
The code for the OnPanUpdated
event handler is then added to the code-behind file:
void OnPanUpdated (object sender, PanUpdatedEventArgs e)
{
// Handle the pan
}
Creating a pan container
This section contains a generalized helper class that performs freeform panning, which is typically suited to navigating within images or maps. Handling the pan gesture to perform this operation requires some math to transform the user interface. This math is used to pan only within the bounds of the wrapped user interface element. The following code example shows the PanContainer
class:
public class PanContainer : ContentView
{
double x, y;
public PanContainer ()
{
// Set PanGestureRecognizer.TouchPoints to control the
// number of touch points needed to pan
var panGesture = new PanGestureRecognizer ();
panGesture.PanUpdated += OnPanUpdated;
GestureRecognizers.Add (panGesture);
}
void OnPanUpdated (object sender, PanUpdatedEventArgs e)
{
...
}
}
This class can be wrapped around a user interface element so that the gesture will pan the wrapped user interface element. The following XAML code example shows the PanContainer
wrapping an Image
element:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PanGesture"
x:Class="PanGesture.HomePage">
<ContentPage.Content>
<AbsoluteLayout>
<local:PanContainer>
<Image Source="MonoMonkey.jpg" WidthRequest="1024" HeightRequest="768" />
</local:PanContainer>
</AbsoluteLayout>
</ContentPage.Content>
</ContentPage>
The following code example shows how the PanContainer
wraps an Image
element in a C# page:
public class HomePageCS : ContentPage
{
public HomePageCS ()
{
Content = new AbsoluteLayout {
Padding = new Thickness (20),
Children = {
new PanContainer {
Content = new Image {
Source = ImageSource.FromFile ("MonoMonkey.jpg"),
WidthRequest = 1024,
HeightRequest = 768
}
}
}
};
}
}
In both examples, the WidthRequest
and HeightRequest
properties are set to the width and height values of the image being displayed.
When the Image
element receives a pan gesture, the displayed image will be panned. The pan is performed by the PanContainer.OnPanUpdated
method, which is shown in the following code example:
void OnPanUpdated (object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType) {
case GestureStatus.Running:
// Translate and ensure we don't pan beyond the wrapped user interface element bounds.
Content.TranslationX =
Math.Max (Math.Min (0, x + e.TotalX), -Math.Abs (Content.Width - App.ScreenWidth));
Content.TranslationY =
Math.Max (Math.Min (0, y + e.TotalY), -Math.Abs (Content.Height - App.ScreenHeight));
break;
case GestureStatus.Completed:
// Store the translation applied during the pan
x = Content.TranslationX;
y = Content.TranslationY;
break;
}
}
This method updates the viewable content of the wrapped user interface element, based on the user's pan gesture. This is achieved by using the values of the TotalX
and TotalY
properties of the PanUpdatedEventArgs
instance to calculate the direction and distance of the pan. The App.ScreenWidth
and App.ScreenHeight
properties provide the height and width of the viewport, and are set to the screen width and screen height values of the device by the respective platform-specific projects. The wrapped user element is then panned by setting its TranslationX
and TranslationY
properties to the calculated values.
When panning content in an element that does not occupy the full screen, the height and width of the viewport can be obtained from the element's Height
and Width
properties.
Note
Displaying high-resolution images can greatly increase an app's memory footprint. Therefore, they should only be created when required and should be released as soon as the app no longer requires them. For more information, see Optimize Image Resources.