Swiping in Xamarin ListView (SfListView)

10 Jul 202324 minutes to read

Overview

The SfListView allows swiping items to do custom actions such as deleting the data, adding the data, editing the data, etc. To enable swiping, set the SfListView.AllowSwiping property to true. Swipe views are displayed when swiping from left to right or right to left (for Horizontal orientation, top to bottom or bottom to top) on the item.

It provides customizable swipe templates for swiping on left and right sides. You can restrict the layout of swipe view up to a certain position when swiping the item by setting the SfListView.SwipeThreshold property. You can set size of the swipe views by setting the SfListView.SwipeOffset property.

NOTE

When SfListView.AutoFitMode is AutoFitMode.Height for main listview, the height of inner listview will change while scrolling the view and items will be refreshed.

NOTE

When tap a swiped item, the SelectionChanging and SelectionChanged events will not occur since the swiped item is reset at this time.

NOTE

When the Visual is Material, you need to set the BackgroundColor to ItemTemplate to show the slide swiping.

Assigning left and right swipe templates

The User Interface (UI) for swiping can be customized by using swipe templates SfListView.LeftSwipeTemplate when swiping towards right and SfListView.RightSwipeTemplate when swiping towards left. The contents inside the swipe template are arranged based on the offset values when swiping an item. You can reset the swiping item or swiped item by calling the SfListView.ResetSwipe method.

<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
  <syncfusion:SfListView x:Name="listView" AllowSwiping="True">
    <syncfusion:SfListView.LeftSwipeTemplate>
      <DataTemplate x:Name="LeftSwipeTemplate">
        <Grid>
          <Grid BackgroundColor="#009EDA" HorizontalOptions="Fill" VerticalOptions="Fill" Grid.Column="0">
            <Grid VerticalOptions="Center" HorizontalOptions="Center">
              <Image Grid.Column="0"
                    Grid.Row="0"
                    BackgroundColor="Transparent"
                    HeightRequest="35"
                    WidthRequest="35"
                    Source="Favorites.png" />
            </Grid>
          </Grid>
        </Grid>
      </DataTemplate>
    </syncfusion:SfListView.LeftSwipeTemplate>
  </syncfusion:SfListView>
</ContentPage>
//Defining left swipe template
listView.LeftSwipeTemplate = new DataTemplate(() =>
{
    var grid = new Grid();

    var grid1 = new Grid() { BackgroundColor = Color.FromHex("#009EDA"), HorizontalOptions = LayoutOptions.Fill, 
                             VerticalOptions = LayoutOptions.Fill };
    var favoriteGrid = new Grid() { HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
    var favoriteImage = new Image() { BackgroundColor = Color.Transparent, HeightRequest = 35, WidthRequest = 35 };
    favoriteImage.Source = ImageSource.FromResource("Swiping.Images.Favorites.png");
    favoriteGrid.Children.Add(favoriteImage);
    grid1.Children.Add(favoriteGrid);

    grid.Children.Add(grid1);

    return grid;

});

NOTE

Similarly, the UI for swiping towards left can be customized by using the SfListView.RightSwipeTemplate.

NOTE

Swipe Template is mandatory to perform swiping in the SfListView.

Left swiping functionalities

Download the entire source code from GitHub here.

Right swiping functionalities

NOTE

To customize the appearance of each swipe item with different templates based on specific constraints by using the DataTemplateSelector.

Working with multiple views in swipe template

The swipe templates allows customizing with custom actions such as deleting the data, adding the data, editing the data, etc. by loading multiple views.

<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
 <syncfusion:SfListView x:Name="listView">
  <syncfusion:SfListView.LeftSwipeTemplate>
    <DataTemplate x:Name="LeftSwipeTemplate">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid BackgroundColor="#009EDA" HorizontalOptions="Fill" VerticalOptions="Fill" Grid.Column="0">
          <Grid VerticalOptions="Center" HorizontalOptions="Center">
            <Image Grid.Column="0"
                   Grid.Row="0"
                   BackgroundColor="Transparent"
                   HeightRequest="35"
                   WidthRequest="35"
                   BindingContextChanged="leftImage_BindingContextChanged"
                   Source="Favorites.png" />
          </Grid>
        </Grid>
        <Grid BackgroundColor="#DC595F" HorizontalOptions="Fill" VerticalOptions="Fill" Grid.Column="1">
          <Grid VerticalOptions="Center" HorizontalOptions="Center">
            <Image Grid.Column="0"
                   Grid.Row="0"
                   HeightRequest="35"
                   WidthRequest="35"
                   BackgroundColor="Transparent"
                   BindingContextChanged="rightImage_BindingContextChanged"
                   Source="Delete.png" />
          </Grid>
        </Grid>
      </Grid>
    </DataTemplate>
  </syncfusion:SfListView.LeftSwipeTemplate>
 </syncfusion:SfListView>
</ContentPage>
listView.LeftSwipeTemplate = new DataTemplate(() =>
{
  var grid = new Grid();

  var grid1 = new Grid()
  {
  BackgroundColor = Color.FromHex("#009EDA"),
  HorizontalOptions = LayoutOptions.Fill,
  VerticalOptions = LayoutOptions.Fill
  };
  var favoriteGrid = new Grid() { HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
  var favoriteImage = new Image() { BackgroundColor = Color.Transparent, HeightRequest = 35, WidthRequest = 35 };
  favoriteImage.Source = ImageSource.FromResource("Swiping.Images.Favorites.png");
  favoriteImage.BindingContextChanged += FavoriteImage_BindingContextChanged;
  favoriteGrid.Children.Add(favoriteImage);
  grid1.Children.Add(favoriteGrid);

  var grid2 = new Grid()
  {
  BackgroundColor = Color.FromHex("#DC595F"),
  HorizontalOptions = LayoutOptions.Fill,
  VerticalOptions = LayoutOptions.Fill
  };
  var deleteGrid = new Grid() { HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
  var deleteImage = new Image() { BackgroundColor = Color.Transparent, HeightRequest = 35, WidthRequest = 35 };
  deleteImage.Source = ImageSource.FromResource("Swiping.Images.Delete.png");
  deleteImage.BindingContextChanged += DeleteImage_BindingContextChanged;
  deleteGrid.Children.Add(deleteImage);
  grid1.Children.Add(deleteGrid);

  grid.Children.Add(grid1);
  grid.Children.Add(grid2, 1, 0);
                
  return grid;
});

Customize left swipe in listview

To delete the item when Delete image is tapped and setting favorites to item when Favorites image is tapped, follow the code example.

Image leftImage;
Image rightImage;
int itemIndex = -1;

private void SetFavorites()
{
   if (itemIndex >= 0)
   {
       var item = viewModel.InboxInfo[itemIndex];
       item.IsFavorite = !item.IsFavorite;
   }
   this.listView.ResetSwipe();
}

private void Delete()
{
   if (itemIndex >= 0)
       viewModel.InboxInfo.RemoveAt(itemIndex);
   this.listView.ResetSwipe();
}

private void ListView_SwipeStarted(object sender, SwipeStartedEventArgs e)
{
   itemIndex = -1;
}

private void ListView_SwipeEnded(object sender, SwipeEndedEventArgs e)
{
   itemIndex = e.ItemIndex;
}

private void leftImage_BindingContextChanged(object sender, EventArgs e)
{
   if (leftImage == null)
   {
      leftImage = sender as Image;
      (leftImage.Parent as View).GestureRecognizers.Add(new TapGestureRecognizer() { Command = new Command(SetFavorites) });
      leftImage.Source = ImageSource.FromResource("Swiping.Images.Favorites.png");
   }
}

private void rightImage_BindingContextChanged(object sender, EventArgs e)
{
   if (rightImage == null)
   {
      rightImage = sender as Image;
      (rightImage.Parent as View).GestureRecognizers.Add(new TapGestureRecognizer() { Command = new Command(Delete) });
      rightImage.Source = ImageSource.FromResource("Swiping.Images.Delete.png");
   }
}

Performing swipe delete operation

To delete an item in view while swiping the item from one extent to other by using SfListView.SwipeEnded event. By setting the SfListView.SwipeOffset value to the view size to swipe the item upto end of the item.

<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
 <syncfusion:SfListView x:Name="listView" 
                 AllowSwiping="True" SelectionMode="None" 
                 SwipeOffset="360" SwipeThreshold="30"
                 SwipeStarted="ListView_SwipeStarted" 
                 SwipeEnded="ListView_SwipeEnded" 
                 Swiping="ListView_Swiping">
  <syncfusion:SfListView.RightSwipeTemplate>
    <DataTemplate x:Name="RightSwipeTemplate">
      <Grid BackgroundColor="#DC595F" HorizontalOptions="Fill" VerticalOptions="Fill">
        <Grid VerticalOptions="Center" HorizontalOptions="Center">
          <Image Grid.Column="0"
                 Grid.Row="0"
                 HeightRequest="35"
                 WidthRequest="35"
                 BackgroundColor="Transparent"
                 Source="Delete.png" />
        </Grid>
      </Grid>
    </DataTemplate>
  </syncfusion:SfListView.RightSwipeTemplate>
 </syncfusion:SfListView>
</ContentPage>
listView.AllowSwiping = true;
listView.SelectionMode = SelectionMode.None;
listView.SwipeOffset = 360;
listView.SwipeThreshold = 30;
listView.SwipeStarted += ListView_SwipeStarted;
listView.SwipeEnded += ListView_SwipeEnded;
listView.Swiping += ListView_Swiping;
listView.RightSwipeTemplate = new DataTemplate(() =>
{
   var grid = new Grid();

   var grid1 = new Grid()
   {
    BackgroundColor = Color.FromHex("#DC595F"),
    HorizontalOptions = LayoutOptions.Fill,
    VerticalOptions = LayoutOptions.Fill
   };
   var deleteGrid = new Grid() { HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
   var deleteImage = new Image() { BackgroundColor = Color.Transparent, HeightRequest = 35, WidthRequest = 35 };
   deleteImage.Source = ImageSource.FromResource("Swiping.Images.Delete.png");
   deleteGrid.Children.Add(deleteImage);
   grid1.Children.Add(deleteGrid);

   grid.Children.Add(grid1);

   return grid;
});

private void ListView_SwipeEnded(object sender, SwipeEndedEventArgs e)
{
  if (e.SwipeOffset >= 360)
  {
     viewModel.InboxInfo.RemoveAt(e.ItemIndex);
     listView.ResetSwipe();
  }
}

Programmatic swiping

Using the SwipeItem method, you can swipe an item programmatically based on the given offset value. You need to pass the item to be swiped and SwipeOffset as a parameter in the SwipeItem method.

Parameters Description
item data Represents the item data of list view item.
offset Represents the value that how much the item need to swipe.
<ContentPage.Content>
    <StackLayout>
        <Grid HeightRequest="50">
            <Button x:Name="RightSwipe" Text="Right Swipe Button" />
            <Button x:Name="LeftSwipe" Text="Left Swipe Button" Grid.Column="1"/>
        </Grid>
        <listView:SfListView x:Name="listView" ItemSize="70" SelectionMode="Single" AllowSwiping="True"
    ItemSpacing="0,0,5,0" >
            <listView:SfListView.LeftSwipeTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            <Grid BackgroundColor="SlateBlue"  HorizontalOptions="Fill" VerticalOptions="Fill">
                                <Label Text="Left Swipe Template" TextColor="White" VerticalOptions="Center" HorizontalOptions="Center"/>
                            </Grid>
                        </ViewCell.View>
                    </ViewCell>
                </DataTemplate>
            </listView:SfListView.LeftSwipeTemplate>
            <listView:SfListView.RightSwipeTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            <Grid BackgroundColor="SlateBlue" HorizontalOptions="Fill" VerticalOptions="Fill">
                                <Label Text="Right Swipe Template" TextColor="White" VerticalOptions="Center"/>
                            </Grid>
                        </ViewCell.View>
                    </ViewCell>
                </DataTemplate>
            </listView:SfListView.RightSwipeTemplate>
        </listView:SfListView>
    </StackLayout>
</ContentPage.Content>

The SwipeOffset value should be positive for the left swiping of the listview item.

private void LeftSwipeButton_Clicked(object sender, EventArgs e)
{
    ListView.SwipeItem(viewModel.contactsinfo[1], 200);
}

The SwipeOffset value should be negative for the right-swiping of the listview item.

private void RightSwipeButton_Clicked(object sender, EventArgs e)
{
    ListView.SwipeItem(viewModel.contactsinfo[1], -150);
}

Programmatic Right and left swiping in listview

Events

SwipeStarted Event

The SfListView.SwipeStarted event is raised when the swipe offset changes from its initial value.

The SwipeStarted event provides the following properties in their arguments:

  • ItemIndex: Defines the swiping item index.
  • ItemData: Defines the underlying data associated with the swiped item. as its arguments.
  • SwipeDirection: Defines the swipe direction of the swiped item.

The SwipeStarted event is used for the following use case:

  • You can cancel the swipe action for a particular item by setting the Cancel property of the SwipeStartedEventArgs.
<syncfusion:SfListView x:Name="listView" ItemsSource="{Binding InboxInfo}" 
                     SwipeStarted="ListView_SwipeStarted" />
listView.SwipeStarted += ListView_SwipeStarted;
private void ListView_SwipeStarted(object sender, SwipeStartedEventArgs e)
{
   if (e.ItemIndex == 1)
      e.Cancel = true;
}

Swiping Event

The SfListView.Swiping event is raised while swiping an item is in progress. This event is triggered with SwipingEventArgs.

The Swiping event provides the following properties in their arguments:

  • ItemIndex: Defines the swiping item index.
  • ItemData: Defines the underlying data associated with the swiped item as its arguments.
  • SwipeDirection: Defines the swipe direction of the swiped item.
  • SwipeOffSet: Defines the current swipe offset of the item being swiped.
  • Handled: Defines that if it is true, current swipe offset value remains same for the swiped item until the SwipeEnded event is raised.

The Swiping event used for the following use cases:

  • To maintain the current offset value for the swiped item till the SwipeEnded event gets called.
  • To hold the swipe view being swiping by setting the Handled property to true if swipe offset meet certain position.
<syncfusion:SfListView x:Name="listView" ItemsSource="{Binding InboxInfo}" 
                       Swiping="ListView_Swiping" />
listView.Swiping += ListView_Swiping;
private void ListView_Swiping(object sender, SwipingEventArgs e)
{
   if (e.ItemIndex == 1 && e.SwipeOffSet > 70)
       e.Handled = true;
}

SwipeEnded Event

The SfListView.SwipeEnded event is fired when completing the swipe action. This event is triggered with SwipeEndedEventArgs.

The SwipeEnded event provides the following properties in their arguments:

  • ItemIndex: Defines the swiping item index.
  • ItemData: Defines the underlying data associated with the swiped item as its arguments.
  • SwipeDirection: Defines the swipe direction of the swiped item.
  • SwipeOffSet: Defines the current swipe offset of the item being swiped.

The SwipeEnded event is used for the following use cases:

  • To insert the data or edit the data after swiped.
  • To delete the item from view after swiping it to certain extent.
  • To reset the swipe view automatically for the swiped item.
<syncfusion:SfListView x:Name="listView" ItemsSource="{Binding InboxInfo}" 
                       SwipeEnded="ListView_SwipeEnded" />
listView.SwipeEnded += ListView_SwipeEnded;
private void ListView_SwipeEnded(object sender, SwipeEndedEventArgs e)
{
  if (e.SwipeOffset > 70)
      listView.ResetSwipe();
}

SwipeReset Event

The SfListView.SwipeReset event is fired when swiping gets reset. The SwipeReset action can be canceled by setting the Cancel property of the ResetSwipeEventArgs to true. This event is triggered with ResetSwipeEventArgs.

SwipeReset event provides the following properties in their arguments:

  • ItemIndex: Defines the swiping item index.
  • ItemData: Defines the underlying data associated with the swiped item as its arguments.
  • SwipeOffSet: Defines the current swipe offset of the item being swiped.

The SwipeReset event used for the following use case:

  • To skip the reset operation for a swiped item.
<syncfusion:SfListView x:Name="listView" ItemsSource="{Binding InboxInfo}" 
                       SwipeReset="ListView_SwipeReset" />
listView.SwipeReset += ListView_SwipeReset;
private void ListView_SwipeReset(object sender, ResetSwipeEventArgs e)
{
  if (e.ItemIndex == 1)
    e.Cancel = true;
}

Limitations

When SfListView is loaded in CarouselView with SfListView.AllowSwiping as false, it behaves in UWP platform as follows:

  • While performing first swipe on the view, it will be handled by ScrollView to ensure whether scrolling is happened or not. If not means the manipulation to parent cannot be passed immediately due to UWP platform behavior. The second swipe will be listened by CarouselView, and the view gets swiped. This is the behavior of the SfListView.

When SfListView is loaded in CarouselView with AllowSwiping as true, it behaves as follows:

  • When swiping in iOS, suddenly carousel swipe happened. To swipe ListViewItem, touch and hold the item for some fraction of seconds (0.25 - 0.5 seconds) and then swipe.
  • When swiping any Item, the SfListView handles the touch and swipe the ListViewItem.
  • After swiping on ListViewItem, SwipeView will load along with it. If you swipe SwipeView element, Carousel view is swiped. Or else swipe on ListViewItem, control handles touching and swiping the item as usual.
  • If you swipe header, footer, or group header elements, Carousel view will swipe in Android platform. But in UWP, first swipe on those elements will be handled by SfListView itself, because manipulation to parent cannot be passed immediately. The second swipe will be listened by CarouselView.

When ListView is loaded in MasterDetailPage with AllowSwiping as true, it behaves as follows:

  • In iOS platform, when swiping a ListViewItem, touch and hold the item for some fraction of seconds (0.25 - 0.5 seconds) and then swipe.

When SfListView.ItemTemplate contains button with AllowSwiping as true, it behaves as follows:

  • While swiping in Android and UWP, button click event executes after swiping.
  • While swiping in iOS, swipe action does not happened when clicking and swiping a button.
  • Swiping will be reset whenever the listview is refreshed like scrolling or any size change is made.

How to reset swipe view automatically?

Swiped item can be reset by defining the SfListView.SwipeOffSet argument of SfListView.SwipeEnded event to 0 when the swiping action is completed.

private void ListView_SwipeEnded(object sender, SwipeEndedEventArgs e)
{
  if (e.SwipeOffset > 70)
      e.SwipeOffset = 0;
}

How to swipe an item indefinitely?

To swipe an item indefinitely, set the SfListView.SwipeOffset property by considering the width or height of the SfListView with SfListView.Orientation accordingly.

ListView.PropertyChanged += ListView_PropertyChanged;

private void ListView_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
  if (e.PropertyName == "Width" && ListView.Orientation == Orientation.Vertical && ListView.SwipeOffset != ListView.Width)
     ListView.SwipeOffset = ListView.Width;
  else if (e.PropertyName == "Height" && ListView.Orientation == Orientation.Horizontal && ListView.SwipeOffset != ListView.Height)
     ListView.SwipeOffset = ListView.Height;
}

Download the entire source code from GitHub here

Indefinite swipe in listview

How to edit data by swiping?

The SfListView allows editing the item data using either SfListView.RightSwipeTemplate or SfListView.LeftSwipeTemplate by loading edit view into the respective template after swiping the item.

<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
 <syncfusion:SfListView > 
  <syncfusion:SfListView.RightSwipeTemplate> 
      <DataTemplate x:Name="RightSwipeTemplate"> 
        <Grid BackgroundColor="#DC595F" HorizontalOptions="Fill" VerticalOptions="Fill"> 
          <Grid> 
            <Label Grid.Row="0" 
                    HeightRequest="50" 
                    WidthRequest="50" 
                    BackgroundColor="Transparent" 
                    Text="EditItem"> 
               <Grid.GestureRecognizers>
                   <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
               </Grid.GestureRecognizers>
            </Label> 
          </Grid> 
        </Grid> 
      </DataTemplate> 
  </syncfusion:SfListView.RightSwipeTemplate> 
 </syncfusion:SfListView>
</ContentPage>
listView.RightSwipeTemplate = new DataTemplate(() =>
{
  var grid = new Grid()
  {
    BackgroundColor = Color.FromHex("#009EDA"),
    HorizontalOptions = LayoutOptions.Fill,
    VerticalOptions = LayoutOptions.Fill
  };

  var grid1 = new Grid();
  TapGestureRecognizer tapped = new TapGestureRecognizer();
  grid1.GestureRecognizers.Add(tapped);
  tapped.Tapped += Grid_Tapped;
  var label = new Label()
  {
    HeightRequest =50,
    WidthRequest = 50,
    BackgroundColor =Color.Transparent,
    Text ="EditItem"
  };

  grid1.Children.Add(label);
  grid.Children.Add(grid1);
  return grid;
});

To set tapped items binding context for pop-up page, follow the code example.

private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
   var popupPage = new SfPopUpView();
   popupPage.BindingContext = (sender as Grid).BindingContext;
   Navigation.PushAsync(popupPage);
}

Download entire source code from GitHub here.

NOTE

You can refer to our Xamarin ListView feature tour page for its groundbreaking feature representations. You can also explore our Xamarin.Forms ListView example to know how to render set of data items with Xamarin.Forms views or custom templates.

See Also

How to swipe an item programmatically in Xamarin.Forms ListView
How to swipe the item indefinitely and layout back on specified position when swipe end
How to swipe an item like Outlook or Gmail application in Xamarin.Forms listview
How to conditionally handle the swiping in Xamarin.Forms ListView (SfListView)