I recently had to implement swipe to dismiss (or delete). The items should get dismissed immediately without a delete button. For Android I used a MvxRecyclerView
and on iOS the good old UITableView
. The example code is available on github.
The impulse for writing this blog post was a tweet by @waniste, who thought it is uncomfortable to implement it with a MvxRecyclerView
. I had to convince him of the opposite, because MvvmCross is awesome and not uncomfortable :P
Seems like implementing "SwipeToDismiss" functionality for MvxRecyclerView isn't very comfortable. Will dig into it another day. #MvvmCross
— Stefan (@waniste) 22. Mai 2016
Core
FirstViewModel
The ViewModel for our view creates the MyItemViewModel
s and passes a deleteCommand
that calls DeleteItem
. deleteCommand
is a command that takes a MyItemViewModel
as parameter. This is the item that should get deleted when the command gets executed. InvokeOnMainThread
is needed, because of iOS.
MyItemViewModel
The MyItemViewModel
is simple, too. It contains only a Text property, and a Delete()
method, that should be called when the swipe gesture has been executed.
Android
Given you have setup a MvxRecyclerView, then it’s pretty easy to implement it. All you need is to inherit a class from ItemTouchHelper.SimpleCallback
and call the Delete
method of your ItemViewModel.
In the constructor we call the base constructor with the allowed directions (ItemTouchHelper.Left | ItemTouchHelper.Right
). In this example you can move the items left and right and you are not allowed to drag it. For the same reason, we simply return false
in OnMove
.
In OnSwiped
, the callback that is called, when the swipe gesture has been recognized, we have to call Delete()
on the currently swiped item. The MvxRecyclerView
is implementing the ViewHolder pattern. This means the DataContext
of the holder is our ViewModel.
Finally, we have to attach it to our recycler view via an ItemTouchHelper
.
iOS
iOS has a built in swipe to dismiss mechanism (UITableView.CommitEditingStyle(...)
). Unfortunately it shows a delete button when swiped, that has to be pressed to actually delete the item. But we want to delete the item immediately. We have to implement our own UIPanGestureRecognizer
for it.
Somewhere in our UITableViewCell
, we attach it to our cell.
Then we need to implement SwipeHandler
that gets called for each swipe interaction of the recognizer.
- When the swipe begins (
UIGestureRecognizerState.Began
) we save the original center of our cell. - When its in between the gesture (
UIGestureRecognizerState.Changed
), we update the center of our cell. We translate it. - When the gesture finishes, we have two options:
- if the cell has not moved more than a defined way, we animate it back
- if the cell has moved more than the defined way, we animate it away and call
Delete()
afterwards
Note: ViewModel
is the casted DataContext
of the cell.
And for some practice, I want to allow only swipes to the left on iOS. Therefore we need to override ShouldBegin
where we check if the initial translation goes left and it goes more horizontal then vertical (else it might be the scroll swipe of the table).
Found a typo? Send me a pull request!