RadListView with swipe: return item to start position after swipe

gestures
swipe

#1

I am trying to implement a simple swiping feature, but return the swiped item to its starting position after the swipe. How can I do this?

Detail:

I have a list of items; when a user swipes one of the items, I want to go to a new page in the app. So far that works. However, if the user goes to the new page, and then hits the “back” button, the swiped item will be off the page, because it has not returned to its original position. Using NativeScript angular.

Goal: after the user swipes an item, that item “bounces back” to its original position.

How can I implement this? I don’t find mention of it in the docks (they seem to assume you want to swipe an item and then freeze it in the swiped position–instead of returning it to its original position like I want).

Here is my current code:

HTML:

<RadListView [items]="storedListThings" (itemSwipeProgressStarted)="onSwipeCellStarted($event)" swipeActions="true">
   <ng-template tkListItemTemplate let-thing="item">
       <StackLayout orientation="vertical" class="listItemStackLayout">
           <Label class="h3"  textWrap="true" text="Swipe Me To Go To New Page!"></Label>
       </StackLayout>
    </ng-template>
</RadListView>

TS:

  onSwipeCellStarted(args) {
    const selectedItem = args.index
    const navigationExtras: NavigationExtras = {
        queryParams: {
          id: selectedItem
         }
      };
    this.router.navigate(["newamazingpage"], navigationExtras)
  }

#2

listview.notifySwipeToExecuteFinished() is what you might need.


#3

Thanks. I have not been able to get it to work. That might be because I am not properly defining “listView” in my angular/ts code. Most of my tries produced errors. The following does not register an error, but it does not do anything–it is the same behavior as before, with the swipe working but the swiped item not returning to its original position:

HTML (same code as above)

TS:

import * as listViewModule from "nativescript-pro-ui/listview";
...
export class...

public listView = new listViewModule.RadListView()

....
onSwipeCellStarted(args) {
  this.listView.notifySwipeToExecuteFinished(); //key line
  const selectedItem = args.index
    const navigationExtras: NavigationExtras = {
        queryParams: {
          id: selectedItem
         }
      };
    this.router.navigate(["newamazingpage"], navigationExtras)
  }

Is this the implementation you had in mind?


#4

Try adding a timeout or try calling .notifySwipeToExecuteFinished() in swipe ended event.


#5

Thanks. I have been able to get it to work with the below code–by adding the set-timeout. I do however find that it acts buggy. Every now and then, it will not work (on the emulator, haven’t been able to test on device yet). So I might do 8 swipes with the swiped item returning to the right position, and then the next swipe does not return.

I have not been able to find out why or from what pattern this is happening. Have you found this to be buggy?

(Note that changing to occur after swipe is complete is not a workable option for the functionality I want)

Taking some action on swipe–like going to a new page–does not seem to make a difference.

FYI for others, below is the code that works for me, except for the strange behavior noted in first paragraph here:

HTML: (same as in original post)

TS:

 onSwipeCellStarted(args) {
   const listViewStuff = args.object 
     setTimeout(() => {
       listViewStuff.notifySwipeToExecuteFinished() // works *most* of the time only
     }, 200);

#6

I would say it’s definitely not buggy, but the way you are using it is not the perfect one.

  1. You can control how much user can swipe the item, how much towards left / right.
  2. So it reaches the limit, by then it calls swipe end and where you can execute this logic.

#7

Thanks. I think my implementation matches what you are saying:

  1. user swipes; 2. “onSwipeCellStarted” function is called, setting limits to how far the swipe can go; and then 3. a separate function is called, taking the action I want (going to new page) and also returning the swiped item to original position with .notifySwipeToExecuteFinished.

The below code seems to be working on emulator. I am including full relevant code in case helpful as reference to others:

*NOTE Using NativeScript Pro-UI with NativeScript Angular

html:


<RadListView [items]="storedListThings" (itemSwipeProgressStarted)="onSwipeCellStarted($event)" swipeActions="true">
   <ng-template tkListItemTemplate let-thing="item">
       <StackLayout orientation="vertical" class="listItemStackLayout">
           <Label class="h3"  textWrap="true" [text]="{{thing}}"></Label>
       </StackLayout>
    </ng-template>
</RadListView>

ts:


import * as Utils from "utils/utils";
...

onSwipeCellStarted(args) {
    const swipeLimits = args.data.swipeLimits; // to set space limit to swipe
    swipeLimits.threshold = 70 * Utils.layout.getDisplayDensity();
    swipeLimits.left = 140 * Utils.layout.getDisplayDensity();
    swipeLimits.right = 140 * Utils.layout.getDisplayDensity();
    this.nextPage(args)
} 

nextPage(args) {
   const listViewStuff = args.object 
   setTimeout(() => {
       listViewStuff.notifySwipeToExecuteFinished() // returns swiped item to original position
     }, 200);
  // following lines are for the action I want to take --going to a new page on swipe:
   const selectedItem = args.index
   const navigationExtras: NavigationExtras = {
        queryParams: {
          id: selectedItem
         }
      };
    this.router.navigate(["amazingnewpage"], navigationExtras) 
  }