RadListView swipe actions acting strange


#1

Hello,

Im trying to follow this guide to implement swipe actions:
http://docs.telerik.com/devtools/nativescript-ui/Controls/Angular/ListView/swipe-actions#implementing-swipe-actions

But what I end up with is this:

When swiping the row, the row is moving as expected but the “mark” and “delete” actions are always visible for some reason. And while trying to swipe on iOS it crashes with this error:

1 0x10a6f97cb NativeScript::FFICallbackNativeScript::ObjCMethodCallback::ffiClosureCallback(ffi_cif*, void*, void**, void*)
2 0x10adce1ee ffi_closure_unix64_inner
3 0x10adceb22 ffi_closure_unix64
4 0x10d8cc966 -[TKListViewCell swipeChanged:]
5 0x10d8cad98 -[TKListViewCell pan:]
6 0x10baef409 -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:]
7 0x10baf71a8 _UIGestureRecognizerSendTargetActions
8 0x10baf4c77 _UIGestureRecognizerSendActions
9 0x10baf3f03 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:]
10 0x10badff7e _UIGestureEnvironmentUpdate
11 0x10badf9c3 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:]
12 0x10badeba6 -[UIGestureEnvironment _updateGesturesForEvent:window:]
13 0x10b624c1d -[UIWindow sendEvent:]
14 0x10b5d19ab -[UIApplication sendEvent:]
15 0x12b41a481 -[UIApplicationAccessibility sendEvent:]
16 0x10bdbe72d __dispatchPreprocessedEventFromEventQueue
17 0x10bdb7463 __handleEventQueue
18 0x10dfec761 CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION
19 0x10dfd198c __CFRunLoopDoSources0
20 0x10dfd0e76 __CFRunLoopRun
21 0x10dfd0884 CFRunLoopRunSpecific
22 0x10f7baa6f GSEventRunModal
23 0x10b5b3c68 UIApplicationMain
24 0x10adce97d ffi_call_unix64
25 0x129c4ff70
file:///app/tns_modules/@angular/core/bundles/core.umd.js:12760:77: JS ERROR Error: Error in pages/list/list.html:16:2 caused by: undefined is not an object (evaluating ‘groceryList.id’)
Feb 4 22:56:57 com.apple.CoreSimulator.SimDevice.A0CDD1AF-56DC-4172-A842-1F4ECAE9F801.launchd_sim[12713] (UIKitApplication:org.nativescript.groceries[0x3947][24378]): Service exited due to Segmentation fault: 11

The code so far looks like this:

<RadListView
    row="1"
    [items]="lists$ | async"
    swipeActions="true"
    (itemSwipeProgressStarted)="onSwipeCellStarted($event)"
    selectionBehavior="None"
    (itemSelected)="onItemSelected($event)"
    (itemDeselected)="onItemDeselected($event)">
    <template tkListItemTemplate let-item="item">
      <StackLayout orientation="vertical">
        <Label class="medium-spacing list-item" [text]="item.name"></Label>
        <StackLayout class="list-divider"></StackLayout>
      </StackLayout>
    </template>

    <GridLayout *tkListItemSwipeTemplate columns="auto, *, auto" class="gridLayoutLayout">
      <StackLayout id="mark-view" col="0" class="markViewStackLayout" (tap)="onLeftSwipeClick($event)">
        <Label text="mark" class="swipetemplateLabel" verticalAlignment="center" horizontalAlignment="center"></Label>
      </StackLayout>
      <StackLayout id="delete-view" col="2" class="deleteViewStackLayout" (tap)="onRightSwipeClick($event)">
        <Label text="delete" class="swipetemplateLabel" verticalAlignment="center" horizontalAlignment="center"></Label>
      </StackLayout>
    </GridLayout>
  </RadListView>

And the TS:

onSwipeCellStarted(args: ListViewEventData) {
    const swipeLimits = args.data.swipeLimits;
    const swipeView = args['object'];
    const leftItem = swipeView.getViewById('mark-view');
    const rightItem = swipeView.getViewById('delete-view');
    swipeLimits.left = leftItem.getMeasuredWidth();
    swipeLimits.right = rightItem.getMeasuredWidth();
    swipeLimits.threshold = leftItem.getMeasuredWidth() / 2;
  }

  onLeftSwipeClick(args: ListViewEventData) {
    console.log("Left swipe click");
  }

  onRightSwipeClick(args: ListViewEventData) {
    console.log("Right swipe click");
  }

#2

Hi,

I had the same issue and solved it by adding padding in the CSS to the classes “markViewStackLayout” and “deleteViewStackLayout”. See https://www.thepolyglotdeveloper.com/2017/03/use-side-drawer-feature-rich-list-view-nativescript-angular-app/ for a full example including CSS.

-Ace


#3

I know this is an old thread, but this suggestion doesn’t seem to work any more. I’m seeing exactly what this question is seeing. I’m even following the example here. The swipe will work, but the actions will always be showing. I’ve even copied the example exactly and it still doesn’t work. Any suggestions?


#4

Here is what I’m doing:

<ActionBar class="action-bar">
    <!-- 
    Use the NavigationButton as a side-drawer button in Android because ActionItems are shown on the right side of the ActionBar
    -->
    <NavigationButton ios:visibility="collapsed" icon="res://menu" (tap)="onDrawerButtonTap()"></NavigationButton>
    <!-- 
    Use the ActionItem for IOS with position set to left. Using the NavigationButton as a side-drawer button in iOS is not possible, because its function is to always navigate back in the application.
    -->
    <ActionItem icon="res://navigation/menu" android:visibility="collapsed" (tap)="onDrawerButtonTap()" ios.position="left">
    </ActionItem>
    <Label class="action-bar-title" text="Dailies"></Label>
</ActionBar>

<!--
RadSideDrawer is a UI component part of the Progress NativeScript UI set of components.
Learn more about the RadSideDrawer UI component and how it can be customized in this documentation article:
http://docs.telerik.com/devtools/nativescript-ui/Controls/Angular/SideDrawer/getting-started
The RadSideDrawer component is designed to be used as a root element and
it shouldn't have any other siblings other than the <ActionBar> component.
-->
<RadSideDrawer #drawer showOverNavigation="true" [drawerTransition]="sideDrawerTransition">
    <!--
    Use the tkDrawerContent directive to display the content of the app drawer on this page.
    -->
    <StackLayout tkDrawerContent>
        <MyDrawer [selectedPage]="'Dailies'"></MyDrawer>
    </StackLayout>

    <!--
    Use the tkMainContent directive to display the content of the page when you have an app drawer.
    -->
    <GridLayout class="page page-content" tkMainContent>
        <RadListView [items]="dailies" swipeActions="true" selectionBehavior="None" (itemSwipeProgressEnded)="onSwipeCellFinished($event)"
            (itemSwipeProgressStarted)="onSwipeCellStarted($event)" (itemSwipeProgressChanged)="onCellSwiping($event)"
            class="list-group custom-list-view">
            <ng-template tkListItemTemplate let-item="item">
                <StackLayout orientation="vertical" class="list-group-item">
                    <Label class="nameLabel" [text]="item.name"></Label>
                </StackLayout>
            </ng-template>
            <GridLayout *tkListItemSwipeTemplate columns="*, auto" class="gridLayoutLayout">
                <StackLayout id="delete-view" col="1" class="deleteViewStackLayout" (tap)="onRightSwipeClick($event)">
                    <Label text="delete" class="swipetemplateLabel" verticalAlignment="center" horizontalAlignment="center"></Label>
                </StackLayout>
            </GridLayout>
        </RadListView>
    </GridLayout>
</RadSideDrawer>

I only want actions on one side. I’ve tried it exactly from the example I reference, with the same result–actions are always visible.

Here are the other files:

import { Component, OnInit, ViewChild } from "@angular/core";
import { ListViewEventData } from "nativescript-ui-listview";
import { DrawerTransitionBase, SlideInOnTopTransition } from "nativescript-ui-sidedrawer";
import { RadSideDrawerComponent } from "nativescript-ui-sidedrawer/angular/side-drawer-directives";
import { ObservableArray } from "tns-core-modules/data/observable-array/observable-array";
import { View } from "tns-core-modules/ui/core/view";
import { DailyItem } from "../models/daily-item";
import { DailyItems } from "../providers/daily-items";

@Component({
    selector: "Dailies",
    moduleId: module.id,
    templateUrl: "./dailies.component.html",
    styleUrls: ["./dailies.component.scss"]
})
export class DailiesComponent implements OnInit {

    dailies: ObservableArray<DailyItem>;

    /* ***********************************************************
    * Use the @ViewChild decorator to get a reference to the drawer component.
    * It is used in the "onDrawerButtonTap" function below to manipulate the drawer.
    *************************************************************/
    @ViewChild("drawer") drawerComponent: RadSideDrawerComponent;

    private _sideDrawerTransition: DrawerTransitionBase;

    constructor(private dailyItems: DailyItems) {
    }

    /* ***********************************************************
    * Use the sideDrawerTransition property to change the open/close animation of the drawer.
    *************************************************************/
    ngOnInit(): void {
        this._sideDrawerTransition = new SlideInOnTopTransition();
        this.refreshItems();
    }

    get sideDrawerTransition(): DrawerTransitionBase {
        return this._sideDrawerTransition;
    }

    /* ***********************************************************
    * According to guidelines, if you have a drawer on your page, you should always
    * have a button that opens it. Use the showDrawer() function to open the app drawer section.
    *************************************************************/
    onDrawerButtonTap(): void {
        this.drawerComponent.sideDrawer.showDrawer();
    }

     // >> angular-listview-swipe-action-release-notify
    onCellSwiping(args: ListViewEventData) {
        const swipeLimits = args.data.swipeLimits;
        const currentItemView = args.object;

        if (args.data.x > 200) {
            console.log("Notify perform left action");
        } else if (args.data.x < -200) {
            console.log("Notify perform right action");
        }
    }
    // << angular-listview-swipe-action-release-notify
    // >> angular-listview-swipe-action-release-limits
    onSwipeCellStarted(args: ListViewEventData) {
        const swipeLimits = args.data.swipeLimits;
        const swipeView = args.object;
        const rightItem = swipeView.getViewById<View>("delete-view");
        swipeLimits.right = rightItem.getMeasuredWidth();
    }
    // << angular-listview-swipe-action-release-limits
    // >> angular-listview-swipe-action-release-execute
    onSwipeCellFinished(args: ListViewEventData) {}

    private async refreshItems() {
        const dailies = await this.dailyItems.getItems();
        this.dailies = new ObservableArray(dailies);
    }
}
.listItemStackLayout {
    background-color: white;
    padding-left: 5;
}

.labelName {
    font-size: 20;
    margin-bottom: 8;
}

.labelTitle {
    font-size: 14;
    font-weight: bold;
}

.labelText {
    font-size: 12;
}

.markViewStackLayout {
    background-color: blue;
    padding: 16
}

.deleteViewStackLayout {
    background-color: red;
    padding: 16;
}

.gridLayoutLayout {
    background-color: white;
}

.swipetemplateLabel {
    size: 20;
}

button {
    font-size: 15;
    horizontal-align: center;
}

#5

This is what I see by the way:


#6

Found this: https://github.com/telerik/nativescript-ui-feedback/issues/124

Helped me fix the issue.