Cell Swipe

The cell swipe feature allows end-users to use swipe gesture on cells. When the user swipes, the content view moves revealing a designated swipe background view where you can place custom views ready for interaction e.g. buttons, images etc.

Properties

The following RadListView properties are related to the sell swiping feature:

  • IsItemSwipeEnabled (bool): Turns on or off the feature. It's default value is false.
  • SwipeThreshhold (double): Gets or sets the length (in pixels) of the swipe gesture which is required to trigger the feature. Any shorter swipe will not be respected. It's default value is 0.
  • SwipeOffset (Thickness): Gets or sets how much the swiped cell will be moved to the side and stick there. It's default value is 100.
  • ItemSwipeContentTemplate (DataTemplate): Gets or sets the content that will be visualized when users swipe a cell.

To enable this feature in a project the IsItemSwipeEnabled property of the RadListView should be set to True.

In Android it is enough to set this property. It will force the swiped item to stick to the corresponding side. Visualizing the underlying SwipeContent.

In iOS however, the SwipeThreshhold property should be set to force the items to stick to the swiped side. This property represents the length of the swipe gesture in pixels that will visualize the DataTemplate defined as ItemSwipeContentTemplate. Any swipe less than this value will not trigger the Cell Swipe.

Methods

The following RadListView methods are related to the sell swiping feature:

  • void EndItemSwipe(bool isAnimated): Moves the swiped item to its default position.

Events

The following RadListView events are related to the sell swiping feature:

  • ItemSwipeStarting: Occurs when the user has initiated swipe gesture. The event arguments are of type ItemSwipeStartingEventArgs, that provides the following properties:
    • Item (object): The item that will be swiped.
    • Cancel (bool): If you set this value to false, the swiping will be canceled.
  • ItemSwiping: Occurs while the user is swiping the item. The event arguments are of type ItemSwipingEventArgs, that provides the following properties:
    • Item (object): The item that is being swiped.
    • Offset (double): The current swipe offset.
  • ItemSwipeCompleted: Occurs when the user finishes the swipe gesture. The event arguments are of type ItemSwipeCompletedEventArgs, that provides the following properties:
    • Item (object): The item that has been swiped.
    • Offset (double): The swipe offset at which the item has been dropped.

Examples

With the RadListView swipe events, we can perform custom actions depending on the swipe direction, the swiped amount or the data item.

Alternatively, we can add interactive elements to the swipe content and use the swipe gesture only to reveal this content. The user then can choose how to interact with the revealed content.

Example with swipe events

The following example demonstrates how to use the ItemSwipeCompleted event and depending on the swipe distance, we will modify the data item or remove it from the source.

CellSwipe

Here is the view model for the list view:

public class Mail : NotifyPropertyChangedBase
{
    bool isUnread;

    public string Sender { get; set; }

    public string Subject { get; set; }

    public bool IsUnread
    {
        get { return isUnread; }
        set
        {
            if (this.isUnread != value)
            {
                isUnread = value;
                OnPropertyChanged();
            }
        }
    }
}

public class ViewModel
{
    public ViewModel()
    {
        this.Source = new ObservableCollection<Mail> {
            new Mail{ Sender = "Terry Tye",  Subject = "Re: Summer Vacation" , IsUnread = true},
            new Mail{ Sender = "Felicia Keegan",  Subject = "Seminar Invitation", IsUnread = true},
            new Mail{ Sender = "Jared Linton",  Subject = "Discount code"},
            new Mail{ Sender = "Mark Therese",  Subject = "Quick feedback", IsUnread = true},
            new Mail{ Sender = "Elvina Randall",  Subject = "Happy Birthday!"},
            new Mail{ Sender = "Emilia Porter",  Subject = "Check the attachment", IsUnread = true},
            new Mail{ Sender = "Jared Linton",  Subject = "Gillian Flynn"},
            new Mail{ Sender = "Felicia Keegan",  Subject = "Re: Summer Vacation"},
            new Mail{ Sender = "Felicia Keegan",  Subject = "Pictures"},
        };
    }

    public ObservableCollection<Mail> Source { get; set; }
}

Below is the setup of the list view. Swiping left or right will reveal content with a hint for what will happen if the user completes the swipe action. Setting the SwipeThreshold and the SwipeOffset to the same value ensures that the action will be performed only when the hint is completely revealed.

<ContentPage.BindingContext>
    <local:ViewModel />
</ContentPage.BindingContext>
<telerikDataControls:RadListView x:Name="listView"
                                 BackgroundColor="White"
                                 IsItemSwipeEnabled="True"
                                 ItemSwipeCompleted="OnItemSwipeCompleted"
                                 ItemsSource="{Binding Source}"
                                 SelectionMode="None"
                                 SwipeOffset="70, 0, 70, 0"
                                 SwipeThreshold="70">
    <telerikDataControls:RadListView.ItemTemplate>
        <DataTemplate>
            <listView:ListViewTemplateCell>
                <listView:ListViewTemplateCell.View>
                    <Grid BackgroundColor="White">
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <StackLayout Margin="10,10,10,0" Orientation="Horizontal">
                            <Image HeightRequest="10"
                                   IsVisible="{Binding IsUnread}"
                                   Source="unread.png"
                                   VerticalOptions="Center"
                                   WidthRequest="10" />
                            <Label FontAttributes="Bold"
                                   FontSize="16"
                                   Text="{Binding Sender}"
                                   TextColor="Black" />
                        </StackLayout>
                        <StackLayout Grid.Row="1"
                                     Margin="10,0,10,10"
                                     Orientation="Horizontal">
                            <Label FontSize="14"
                                   Text="Subject:"
                                   TextColor="Gray" />
                            <Label FontSize="14"
                                   Text="{Binding Subject}"
                                   TextColor="Gray" />
                        </StackLayout>
                    </Grid>
                </listView:ListViewTemplateCell.View>
            </listView:ListViewTemplateCell>
        </DataTemplate>
    </telerikDataControls:RadListView.ItemTemplate>
    <telerikDataControls:RadListView.ItemSwipeContentTemplate>
        <DataTemplate>
            <Grid Margin="0"
                  Padding="0"
                  ColumnSpacing="0"
                  RowSpacing="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="70" />
                </Grid.ColumnDefinitions>
                <Label BackgroundColor="#2474d2"
                       HorizontalTextAlignment="Center"
                       Text="Mark as read"
                       TextColor="White"
                       VerticalTextAlignment="Center"
                       WidthRequest="70" />
                <Label Grid.Column="2"
                       BackgroundColor="Red"
                       HorizontalTextAlignment="Center"
                       Text="delete"
                       TextColor="White"
                       VerticalTextAlignment="Center"
                       WidthRequest="70" />
            </Grid>
        </DataTemplate>
    </telerikDataControls:RadListView.ItemSwipeContentTemplate>
</telerikDataControls:RadListView>

Where:

xmlns:telerikDataControls="clr-namespace:Telerik.XamarinForms.DataControls;assembly=Telerik.XamarinForms.DataControls"
xmlns:telerikListView="clr-namespace:Telerik.XamarinForms.DataControls.ListView;assembly=Telerik.XamarinForms.DataControls"

Finally, here is what happens when the user has completed the swipe gesture:

void OnItemSwipeCompleted(object sender, ItemSwipeCompletedEventArgs e)
{
    var listView = sender as RadListView;
    var item = e.Item as Mail;

    listView.EndItemSwipe();

    if (e.Offset >= 70)
    {
        item.IsUnread = false;
    }
    else if (e.Offset <= -70)
    {
        (listView.ItemsSource as ObservableCollection<Mail>).Remove(item);
    }
}

We call the EndItemSwipe() method to force the item to go to its default position, since the scenario does not require any interaction with the swipe content itself.

Example with interactive content

The following example demonstrates how to add a delete button to the swipe content and using the button Clicked event handler, delete an item from the list view source.

CellSwipe

Here is the view model for the list view.

public class Book
{
    public string Title { get; set; }
    public string Author { get; set; }
}

public class ViewModel
{
    public ViewModel()
    {
        this.Source = new ObservableCollection<Book> {
            new Book{ Title = "The Fault in Our Stars ",  Author = "John Green"},
            new Book{ Title = "Divergent",  Author = "Veronica Roth"},
            new Book{ Title = "Gone Girl",  Author = "Gillian Flynn"},
            new Book{ Title = "Clockwork Angel",  Author = "Cassandra Clare" },
            new Book{ Title = "The Martian",  Author = "Andy Weir"},
            new Book{ Title = "Ready Player One",  Author = "Ernest Cline"},
            new Book{ Title = "The Lost Hero",  Author = "Rick Riordan" },
            new Book{ Title = "All the Light We Cannot See",  Author = "Anthony Doerr"},
            new Book{ Title = "Cinder",  Author = "Marissa Meyer"},
            new Book{ Title = "Me Before You",  Author = "Jojo Moyes"},
            new Book{ Title = "The Night Circus",  Author = "Erin Morgenstern"},
        };
    }

    public ObservableCollection<Book> Source { get; set; }
}

Below is the setup of the list view. Note that the SwipeOffset is equal to the width of the button in the swipe content. Thus when the swipe is complete, the revealed content will be the whole button.

<ContentPage.BindingContext>
    <local:ViewModel />
</ContentPage.BindingContext>
<telerikDataControls:RadListView x:Name="listView"
                                 BackgroundColor="White"
                                 IsItemSwipeEnabled="True"
                                 ItemsSource="{Binding Source}"
                                 SelectionMode="None"
                                 SwipeOffset="70, 0, 0, 0"
                                 SwipeThreshold="10">
    <telerikDataControls:RadListView.ItemTemplate>
        <DataTemplate>
            <telerikListView:ListViewTemplateCell>
                <telerikListView:ListViewTemplateCell.View>
                    <Grid>
                        <Label Margin="10,10,10,0"
                               FontAttributes="Bold"
                               FontSize="16"
                               Text="{Binding Title}"
                               TextColor="Black" />
                        <Label Grid.Row="1"
                               Margin="10,0,10,10"
                               FontAttributes="Italic"
                               FontSize="13"
                               Text="{Binding Author}"
                               TextColor="Gray" />
                    </Grid>
                </telerikListView:ListViewTemplateCell.View>
            </telerikListView:ListViewTemplateCell>
        </DataTemplate>
    </telerikDataControls:RadListView.ItemTemplate>
    <telerikDataControls:RadListView.ItemSwipeContentTemplate>
        <DataTemplate>
            <Grid Margin="0"
                  Padding="0"
                  ColumnSpacing="0"
                  RowSpacing="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Button Margin="0"
                        BackgroundColor="Red"
                        BorderRadius="0"
                        Clicked="RemoveBook"
                        Image="delete.png"
                        WidthRequest="70" />
            </Grid>
        </DataTemplate>
    </telerikDataControls:RadListView.ItemSwipeContentTemplate>
</telerikDataControls:RadListView>

Where:

xmlns:telerikDataControls="clr-namespace:Telerik.XamarinForms.DataControls;assembly=Telerik.XamarinForms.DataControls"
xmlns:telerikListView="clr-namespace:Telerik.XamarinForms.DataControls.ListView;assembly=Telerik.XamarinForms.DataControls"

The BindingContext of the swipe content is the data item. This could be used to perform operations on the data. In our case we will delete the item from the source.

void RemoveBook(object sender, EventArgs e)
{
    var item = (sender as BindableObject).BindingContext as Book;
    (this.BindingContext as ViewModel).Source.Remove(item);
}

See Also