Swipe to dismiss with MvvmCross

This is how you can implement swipe to dismiss with MvvmCross

Posted by Sven-Michael Stübe on May 22, 2016

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

Core

FirstViewModel

The ViewModel for our view creates the MyItemViewModels 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.

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.

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).